通过 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并更新您的数组以获得正确的结果。