我正在尝试获取一些有关 GPU 的统计数据。主要是我想获取总 VRAM 和使用量,以及 GPU 利用率(更喜欢 3d 核心,但会满足总使用量)。
闲逛了一段时间后,我发现我可以使用以下程序显示所有 PDH 计数器。
#include <windows.h>
#include <iostream>
#include <pdh.h>
#include <pdhmsg.h>
#pragma comment(lib, "pdh.lib")
void browseCounters() {
PDH_BROWSE_DLG_CONFIG dlgConfig = {0};
dlgConfig.bIncludeInstanceIndex = FALSE;
dlgConfig.bSingleCounterPerAdd = TRUE;
dlgConfig.bSingleCounterPerDialog = TRUE;
dlgConfig.bLocalCountersOnly = FALSE;
dlgConfig.bWildCardInstances = TRUE;
dlgConfig.bHideDetailBox = TRUE;
dlgConfig.bInitializePath = FALSE;
dlgConfig.bDisableMachineSelection = FALSE;
dlgConfig.bIncludeCostlyObjects = FALSE;
dlgConfig.bShowObjectBrowser = FALSE;
dlgConfig.hWndOwner = NULL;
dlgConfig.szReturnPathBuffer = new char[PDH_MAX_COUNTER_PATH];
dlgConfig.cchReturnPathLength = PDH_MAX_COUNTER_PATH;
dlgConfig.pCallBack = NULL;
dlgConfig.dwCallBackArg = 0;
dlgConfig.CallBackStatus = ERROR_SUCCESS;
dlgConfig.dwDefaultDetailLevel = PERF_DETAIL_WIZARD;
// Create a non-const copy of the string literal
char *caption = new char[17];
strcpy(caption, "Select a counter");
dlgConfig.szDialogBoxCaption = caption;
PDH_STATUS status = PdhBrowseCounters(&dlgConfig);
if (status == ERROR_SUCCESS) {
std::wcout << L"Selected Counter: " << dlgConfig.szReturnPathBuffer << std::endl;
} else {
std::cout << "Error: " << status << std::endl;
}
delete[] dlgConfig.szReturnPathBuffer;
}
int main() {
browseCounters();
system("pause");
return 0;
}
浏览完可用的柜台后,我看到一些正是我想要的。我看到有一个 GPU 引擎选项卡。选择该选项并单击“确定”后,我会得到计数器“\GPU Engine(*)\Utilization Percentage”。使用此计数器始终返回 0 利用率百分比。我尝试过使用不同的计数器并将我的 GPU 名称放入计数器路径中,但我无法使其正常工作。
这是我遇到问题的功能。 Main 调用此函数,而 while 循环会永远打印 GPU 利用率。
void printGPU() {
PDH_HQUERY gpuQuery;
PDH_HCOUNTER gpuCounter;
// Open a query
PdhOpenQueryW(NULL, 0, &gpuQuery);
// Replace "Your_GPU_Instance_Name" with the actual name of your GPU instance
wchar_t gpuCounterPath[MAX_PATH];
swprintf_s(gpuCounterPath, L"\\GPU Engine(*)\\Utilization Percentage");
PDH_STATUS pdhStatus = PdhAddCounterW(gpuQuery, gpuCounterPath, 0, &gpuCounter);
if (pdhStatus != ERROR_SUCCESS) {
std::cerr << "Error adding GPU counter: " << pdhStatus << std::endl;
return;
}
while (true) { // Adjust the loop condition based on your needs
// Collect data
PdhCollectQueryData(gpuQuery);
// Wait for a short period (e.g., 1 second)
Sleep(1000);
// Collect data again
PdhCollectQueryData(gpuQuery);
// Read and update GPU usage
PDH_FMT_COUNTERVALUE counterValue;
PdhGetFormattedCounterValue(gpuCounter, PDH_FMT_DOUBLE, NULL, &counterValue);
double gpuUsage = counterValue.doubleValue;
std::cout << "GPU Utilization: " << gpuUsage << "%" << std::endl;
}
// Close the query
PdhCloseQuery(gpuQuery);
}
我正在对 CPU 做同样的事情,并且它工作正常。我只是更新核心列表及其使用百分比。这让我怀疑路径不正确。
void GetCpuUsage() { // Function to get CPU usage percentage for each core
PDH_HQUERY coresQuery;
PDH_HCOUNTER counters[numCores]; // numcores is gotten earier in the code and is set to be the number of system cores
PDH_HCOUNTER totalCounter; // New counter for total CPU usage
// Open a query
PdhOpenQuery(NULL, 0, &coresQuery);
// Add counters for each CPU core
for (int i = 0; i < numCores; ++i) {
wchar_t counterPath[MAX_PATH];
swprintf_s(counterPath, L"\\Processor(%d)\\%% Processor Time", i);
// Convert wide string to narrow string
char narrowCounterPath[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, counterPath, -1, narrowCounterPath, MAX_PATH, NULL, NULL);
PdhAddCounter(coresQuery, narrowCounterPath, 0, &counters[i]);
}
// Add counter for total CPU usage
wchar_t totalCounterPath[MAX_PATH];
swprintf_s(totalCounterPath, L"\\Processor(_Total)\\%% Processor Time");
// Convert wide string to narrow string
char narrowTotalCounterPath[MAX_PATH];
WideCharToMultiByte(CP_ACP, 0, totalCounterPath, -1, narrowTotalCounterPath, MAX_PATH, NULL, NULL);
PdhAddCounter(coresQuery, narrowTotalCounterPath, 0, &totalCounter);
while(pollCPUusage) { // loop forever while main program is open
// Collect data
PdhCollectQueryData(coresQuery);
// Wait for a short period (e.g., 1 second)
Sleep(500);
// Collect data again
PdhCollectQueryData(coresQuery);
// critical section
{
// lock mutex
std::lock_guard<std::mutex> lock(coresMutex);
// Read and update CPU usage for each core
for (int i = 0; i < numCores; ++i) {
PDH_FMT_COUNTERVALUE counterValue;
PdhGetFormattedCounterValue(counters[i], PDH_FMT_DOUBLE, NULL, &counterValue);
cores[i] = counterValue.doubleValue;
//std::cout << "CPU Core " << i << " Usage: " << counterValue.doubleValue << "%" << std::endl;
}
// Read and update total CPU usage
PDH_FMT_COUNTERVALUE totalCounterValue;
PdhGetFormattedCounterValue(totalCounter, PDH_FMT_DOUBLE, NULL, &totalCounterValue);
totalPctUsage = totalCounterValue.doubleValue;
} // end of critical section mutex auto unlocks at this point
}
// Close the query
PdhCloseQuery(coresQuery);
}
非常感谢任何帮助。
您的 GPU 计数器的实例名称中包含通配符 (*)。因此,您需要使用 PdhGetFormattedCounterArray 函数而不是 PdhGetFormattedCounterValue (https://learn.microsoft.com/en-us/windows/win32/api/pdh/nf-pdh-pdhgetformattedcounterarrayw)。要计算 GPU 总利用率,请循环返回数组中的所有条目并将它们相加。