通过 WinAPI 计算每个内核的使用量 CPU
Calculating CPU usage per core by WinAPI
我正在尝试使用 C++ 和 WinAPI 计算每个内核的 CPU 使用率,但我无法正确计算。因此,我设法通过以下方式计算它:
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <windows.h>
#define SystemProcessorPerformanceInformation 0x8
#define SystemBasicInformation 0x0
int _tmain(int argc, _TCHAR* argv[])
{
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
{
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER Reserved1[2];
ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
typedef struct _SYSTEM_BASIC_INFORMATION {
ULONG Reserved;
ULONG TimerResolution;
ULONG PageSize;
ULONG NumberOfPhysicalPages;
ULONG LowestPhysicalPageNumber;
ULONG HighestPhysicalPageNumber;
ULONG AllocationGranularity;
ULONG_PTR MinimumUserModeAddress;
ULONG_PTR MaximumUserModeAddress;
KAFFINITY ActiveProcessorsAffinityMask;
CCHAR NumberOfProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
// SYSTEM_INFO sysinf;
if (argc<2)
{
printf("Please specify waiting time in seconds\n");
return -1;
}
int nWaitSec = _wtoi(argv[1]);
if (nWaitSec <= 0)
{
printf("Waiting interval in seconds should be positive integer\n");
return -1;
}
typedef DWORD(WINAPI * PNTQUERYSYSYTEMINFORMATION)(DWORD info_class, void *out, DWORD size, DWORD *out_size);
PNTQUERYSYSYTEMINFORMATION pNtQuerySystemInformation = NULL;
pNtQuerySystemInformation = (PNTQUERYSYSYTEMINFORMATION)GetProcAddress(GetModuleHandle(L"NTDLL.DLL"), "NtQuerySystemInformation");
SYSTEM_BASIC_INFORMATION sbi;
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION * spi;
DWORD returnlength;
DWORD status = pNtQuerySystemInformation(SystemBasicInformation, &sbi,
sizeof(SYSTEM_BASIC_INFORMATION), &returnlength);
spi = new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[sbi.NumberOfProcessors];
memset(spi, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*sbi.NumberOfProcessors);
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, spi,
(sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*sbi.NumberOfProcessors), &returnlength);
int numberOfCores = returnlength / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
printf("Number of cores: %d\n", numberOfCores);
static ULARGE_INTEGER ul_sys_idle_old[32];
static ULARGE_INTEGER ul_sys_kernel_old[32];
static ULARGE_INTEGER ul_sys_user_old[32];
float usage = 0;
float usageAccum = 0;
printf("\n\nWait for %d seconds\n", nWaitSec);
Sleep(nWaitSec*1000);
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, spi,
(sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*numberOfCores), &returnlength);
usageAccum = 0;
for (int ii = 0; ii<numberOfCores; ii++)
{
ULARGE_INTEGER ul_sys_idle;
ULARGE_INTEGER ul_sys_kernel;
ULARGE_INTEGER ul_sys_user;
ul_sys_idle.QuadPart = spi[ii].IdleTime.QuadPart;
ul_sys_kernel.QuadPart = spi[ii].KernelTime.QuadPart;
ul_sys_user.QuadPart = spi[ii].UserTime.QuadPart;
ULONGLONG kernelTime = (ul_sys_kernel.QuadPart - ul_sys_kernel_old[ii].QuadPart);
ULONGLONG usertime = (ul_sys_user.QuadPart - ul_sys_user_old[ii].QuadPart);
ULONGLONG idletime = (ul_sys_idle.QuadPart - ul_sys_idle_old[ii].QuadPart);
ULONGLONG proctime = kernelTime + usertime - idletime;
ULONGLONG totaltime = kernelTime + usertime;
usage = (float)(proctime * 100) / totaltime;
usageAccum += usage;
printf("Core : %u: Usage : %f%%\n", ii + 1, usage);
}
usageAccum /= numberOfCores;
printf("----------------\nAverage for the last %d seconds: %f", nWaitSec, usageAccum);
delete[] spi;
return 0;
}
尽管如此,它的计算方式似乎是错误的,因为它的输出数据几乎没有变化。我怎样才能正确找到每个内核的 CPU 使用情况?
这三个数组在你的源码中没有实时更新code.So它们的值在循环中始终为0
static ULARGE_INTEGER ul_sys_idle_old[32];
static ULARGE_INTEGER ul_sys_kernel_old[32];
static ULARGE_INTEGER ul_sys_user_old[32];
得到的是CPU使用时间已经运行很久了,基数很大,导致基本不变
您可以参考Correct way to get Windows CPU utilization for multiprocessor并更新您的数组以获得正确的结果。
我正在尝试使用 C++ 和 WinAPI 计算每个内核的 CPU 使用率,但我无法正确计算。因此,我设法通过以下方式计算它:
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <windows.h>
#define SystemProcessorPerformanceInformation 0x8
#define SystemBasicInformation 0x0
int _tmain(int argc, _TCHAR* argv[])
{
typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION
{
LARGE_INTEGER IdleTime;
LARGE_INTEGER KernelTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER Reserved1[2];
ULONG Reserved2;
} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION;
typedef struct _SYSTEM_BASIC_INFORMATION {
ULONG Reserved;
ULONG TimerResolution;
ULONG PageSize;
ULONG NumberOfPhysicalPages;
ULONG LowestPhysicalPageNumber;
ULONG HighestPhysicalPageNumber;
ULONG AllocationGranularity;
ULONG_PTR MinimumUserModeAddress;
ULONG_PTR MaximumUserModeAddress;
KAFFINITY ActiveProcessorsAffinityMask;
CCHAR NumberOfProcessors;
} SYSTEM_BASIC_INFORMATION, *PSYSTEM_BASIC_INFORMATION;
// SYSTEM_INFO sysinf;
if (argc<2)
{
printf("Please specify waiting time in seconds\n");
return -1;
}
int nWaitSec = _wtoi(argv[1]);
if (nWaitSec <= 0)
{
printf("Waiting interval in seconds should be positive integer\n");
return -1;
}
typedef DWORD(WINAPI * PNTQUERYSYSYTEMINFORMATION)(DWORD info_class, void *out, DWORD size, DWORD *out_size);
PNTQUERYSYSYTEMINFORMATION pNtQuerySystemInformation = NULL;
pNtQuerySystemInformation = (PNTQUERYSYSYTEMINFORMATION)GetProcAddress(GetModuleHandle(L"NTDLL.DLL"), "NtQuerySystemInformation");
SYSTEM_BASIC_INFORMATION sbi;
SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION * spi;
DWORD returnlength;
DWORD status = pNtQuerySystemInformation(SystemBasicInformation, &sbi,
sizeof(SYSTEM_BASIC_INFORMATION), &returnlength);
spi = new SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION[sbi.NumberOfProcessors];
memset(spi, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*sbi.NumberOfProcessors);
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, spi,
(sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*sbi.NumberOfProcessors), &returnlength);
int numberOfCores = returnlength / sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION);
printf("Number of cores: %d\n", numberOfCores);
static ULARGE_INTEGER ul_sys_idle_old[32];
static ULARGE_INTEGER ul_sys_kernel_old[32];
static ULARGE_INTEGER ul_sys_user_old[32];
float usage = 0;
float usageAccum = 0;
printf("\n\nWait for %d seconds\n", nWaitSec);
Sleep(nWaitSec*1000);
status = pNtQuerySystemInformation(SystemProcessorPerformanceInformation, spi,
(sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)*numberOfCores), &returnlength);
usageAccum = 0;
for (int ii = 0; ii<numberOfCores; ii++)
{
ULARGE_INTEGER ul_sys_idle;
ULARGE_INTEGER ul_sys_kernel;
ULARGE_INTEGER ul_sys_user;
ul_sys_idle.QuadPart = spi[ii].IdleTime.QuadPart;
ul_sys_kernel.QuadPart = spi[ii].KernelTime.QuadPart;
ul_sys_user.QuadPart = spi[ii].UserTime.QuadPart;
ULONGLONG kernelTime = (ul_sys_kernel.QuadPart - ul_sys_kernel_old[ii].QuadPart);
ULONGLONG usertime = (ul_sys_user.QuadPart - ul_sys_user_old[ii].QuadPart);
ULONGLONG idletime = (ul_sys_idle.QuadPart - ul_sys_idle_old[ii].QuadPart);
ULONGLONG proctime = kernelTime + usertime - idletime;
ULONGLONG totaltime = kernelTime + usertime;
usage = (float)(proctime * 100) / totaltime;
usageAccum += usage;
printf("Core : %u: Usage : %f%%\n", ii + 1, usage);
}
usageAccum /= numberOfCores;
printf("----------------\nAverage for the last %d seconds: %f", nWaitSec, usageAccum);
delete[] spi;
return 0;
}
尽管如此,它的计算方式似乎是错误的,因为它的输出数据几乎没有变化。我怎样才能正确找到每个内核的 CPU 使用情况?
这三个数组在你的源码中没有实时更新code.So它们的值在循环中始终为0
static ULARGE_INTEGER ul_sys_idle_old[32];
static ULARGE_INTEGER ul_sys_kernel_old[32];
static ULARGE_INTEGER ul_sys_user_old[32];
得到的是CPU使用时间已经运行很久了,基数很大,导致基本不变
您可以参考Correct way to get Windows CPU utilization for multiprocessor并更新您的数组以获得正确的结果。