Windows — Как определить потребление процессора в C ++ на ядро

Как получить нагрузку на процессор на ядро ​​(четырехъядерный процессор с гиперпоточностью) в C ++?
Я ищу результат, как в диспетчере задач в%.

Я пытаюсь сделать это сейчас так:
Проблема в том, что код распознает 9 ядер (у меня 8: /)

#define _WIN32_DCOM
#include <iostream>
#include <comdef.h>
#include <Wbemidl.h>

# pragma comment(lib, "wbemuuid.lib")
using namespace std;
bool getCpuLoadInfo() {
HRESULT hres;

// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------

hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
return 0;                  // Program has failed.
}

// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------

hres = CoInitializeSecurity(
NULL,
-1,                          // COM authentication
NULL,                        // Authentication services
NULL,                        // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT,   // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL,                        // Authentication info
EOAC_NONE,                   // Additional capabilities
NULL                         // Reserved
);if (FAILED(hres)) {
cout << "Failed to initialize security. Error code = 0x"<< hex << hres << endl;
CoUninitialize();
return 0;                    // Program has failed.
}

// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------

IWbemLocator *pLoc = NULL;

hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *)&pLoc);

if (FAILED(hres)) {
cout << "Failed to create IWbemLocator object."<< " Err code = 0x"<< hex << hres << endl;
CoUninitialize();
return 0;                 // Program has failed.
}

// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method

IWbemServices *pSvc = NULL;

// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL,                    // User name. NULL = current user
NULL,                    // User password. NULL = current
0,                       // Locale. NULL indicates current
NULL,                    // Security flags.
0,                       // Authority (e.g. Kerberos)
0,                       // Context object
&pSvc                    // pointer to IWbemServices proxy
);

if (FAILED(hres)) {
cout << "Could not connect. Error code = 0x" << hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 0;                // Program has failed.
}

cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------

hres = CoSetProxyBlanket(
pSvc,                        // Indicates the proxy to set
RPC_C_AUTHN_WINNT,           // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE,            // RPC_C_AUTHZ_xxx
NULL,                        // Server principal name
RPC_C_AUTHN_LEVEL_CALL,      // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL,                        // client identity
EOAC_NONE                    // proxy capabilities
);

if (FAILED(hres)) {
cout << "Could not set proxy blanket. Error code = 0x"<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 0;               // Program has failed.
}

// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----

// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
IWbemClassObject *pclsObj;
int i;
while (1) {
i = 1;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor"),

WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);

if (FAILED(hres)) {
cout << "Query for operating system name failed."<< " Error code = 0x"<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 0;               // Program has failed.
}

// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------ULONG uReturn = 0;

while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);

if (0 == uReturn) {
break;
}

VARIANT vtProp;

// Get the value of the Name property
//hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
hr = pclsObj->Get(L"PercentProcessorTime", 0, &vtProp, 0, 0);
wcout << " CPU Usage of CPU " << i << " : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);

//IMPORTANT!!
pclsObj->Release();

i++;
}

}

// Cleanup
// ========

pSvc->Release();
pLoc->Release();
pEnumerator->Release();
pclsObj->Release();
CoUninitialize();

return 0;   // Program successfully completed.
}

Есть ли другой (возможно, более простой) способ получить загрузку процессора на ядро ​​в%?
Или я на правильном пути, но что-то не так с моим кодом?
Если так, что не так с этим? :П

2

Решение

C ++ как язык не предоставляет возможностей для определения этого. Компилятор просто генерирует код, который выполняет то, что запрашивается.

Другой аспект. Ваш сценарий широко использует функции операционной системы, которые включают обработку в различных процессах и в ядре. Скорее всего, вы хотите знать сумму всех действий, а не только количество циклов ЦП, потребляемых вашим конкретным процессом.

Тем не менее, вы можете сделать косвенные измерения. Я бы порекомендовал вам запустить свой сценарий в нескольких потоках одновременно (и повторять его много раз для каждого потока) и измерить астрономическое время, затрачиваемое каждым потоком. Если вы будете следить за потреблением ЦП / памяти / ввода-вывода в диспетчере задач и сравнивать эту информацию со средним временем, потраченным потоками, вы сможете получить оценку того, что ваш сценарий «стоит».

Есть еще один аспект. Ваш результат будет только оценкой, которая будет зависеть от фактической конфигурации вашего окна Windows (член домена или нет) и т. Д. CoInitializeSecurity зависит от различных настроек безопасности и типа учетной записи, которая ее вызывает. На коробке и в домене есть множество вариантов настройки безопасности. Но все-таки даже не очень достоверная оценка лучше, чем ничего.

1

Другие решения

Последнее число является значением _Total, и поэтому вы видите 9 ядер вместо 8, вы можете показать результаты, основанные на количестве ядер. Для получения количества ядер используйте следующую команду:

SYSTEM_INFO systemInfo;

GetSystemInfo( &systemInfo );
numberofCPU = systemInfo.dwNumberOfProcessors;
1

По вопросам рекламы [email protected]