我有一个温度监控程序,我写了一个回来,它监视我的AMD显卡上的温度和风扇,检查风扇故障或过热。 它的问题在于,它需要事先知道哪个进程将使用GPU(graphics处理单元),以杀死它或优雅地停止以避免过热。
为了使我的程序更具dynamic性,我需要一种方法来查找哪个进程正在使用GPU,就像哪个进程正在使用CPU时间(任务pipe理器)一样。 一个这样的应用程序是来自SysInternals的Process Explorer。
我问,我怎样才能在C在Windows中做到这一点? 我知道,如果有这样的方式,它将瞄准Vista和以上。
如果您使用的是Tesla主板或高端Quadro,并且在Windows server 2008 R2 64位 ,Windows 7 64位 (或32/64位Linux)上运行,则可以使用NVML来完成此操作。
下载最新的NVML SDK(Tespla部署工具包) ,看看这两个功能:
nvmlReturn_t nvmlDeviceGetComputeRunningProcesses (nvmlDevice_t device, unsigned int infoCount, nvmlProcessInfo_t * infos) nvmlReturn_t nvmlDeviceGetTemperature (nvmlDevice_t device, nvmlTemperatureSensors_t sensorType, unsigned int * temp)
当心:
nvmlReturn_t nvmlDeviceGetFanSpeed (nvmlDevice_t device, unsigned int * speed)
它“检索设备风扇的预期运行速度”不是真正的风扇速度。 所以你不能用它来检查风扇故障。
我不知道nvmlDeviceGetComputeRunningProcesses替代品可以在GeForce开发板上工作,但是Windows NvAPI (它也适用于GeForce)允许查询风扇转速和温度。
你需要调用一些没有记录的direct3d API函数D3DKMTQueryStatistics。
来自ProcessHacker论坛的示例代码:
#define _Field_size_(...) #define _Field_size_bytes_(...) #define _In_reads_bytes_opt_(...) #define _Out_writes_bytes_all_opt_(...) #define _Field_size_bytes_part_(...) #define _In_range_(...) #define _Out_writes_bytes_(...) #define _Check_return_ #define _Inout_ #define _In_ #define _Out_ #define NTDDI_VERSION NTDDI_WIN7 #include <windows.h> #include <tchar.h> #include <stdio.h> #include "d3dkmthk.h" #pragma comment(lib, "gdi32.lib") // Doesn't do much, since it doesn't have the exports anyway... #pragma comment(lib, "advapi32.lib") typedef NTSTATUS (APIENTRY *PD3DKMTQueryStatistics)(_In_ CONST D3DKMT_QUERYSTATISTICS*); typedef NTSTATUS (APIENTRY *PD3DKMTOpenAdapterFromDeviceName)(_Inout_ D3DKMT_OPENADAPTERFROMDEVICENAME*); int _tmain(int argc, TCHAR *argv[]) { LUID luid = { 20 }; TOKEN_PRIVILEGES privs = { 1, { luid, SE_PRIVILEGE_ENABLED } }; HANDLE hToken; if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) { if (AdjustTokenPrivileges(hToken, FALSE, &privs, sizeof(privs), NULL, NULL)) { } else { return -1; } } else { return -2; } D3DKMT_OPENADAPTERFROMDEVICENAME name = { _T("\\\\?\\pci#ven_10de&dev_0a2b&subsys_9072104d&rev_a2#4&12796cb&0&0008#{1ca05180-a699-450a-9a0c-de4fbe3ddd89}") }; HMODULE hGdi32 = LoadLibrary(_T("gdi32.dll")); PD3DKMTOpenAdapterFromDeviceName D3DKMTOpenAdapterFromDeviceName = (PD3DKMTOpenAdapterFromDeviceName)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromDeviceName"); NTSTATUS status = D3DKMTOpenAdapterFromDeviceName(&name); if (status == 0) { _tprintf(_T("name.AdapterLuid: %llx\n"), name.AdapterLuid); HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId()); _tprintf(_T("hProcess: %#p\n"), hProcess); if (hProcess != NULL) { for (;;) { PD3DKMTQueryStatistics D3DKMTQueryStatistics = (PD3DKMTQueryStatistics)GetProcAddress(hGdi32, "D3DKMTQueryStatistics"); D3DKMT_QUERYSTATISTICS stats = { D3DKMT_QUERYSTATISTICS_PROCESS, name.AdapterLuid, hProcess }; status = D3DKMTQueryStatistics(&stats); if (status == 0) { _tprintf(_T("Usage: %#llx\n"), stats.QueryResult.ProcessInformation.SystemMemory.BytesAllocated); } else { break; } fflush(stdout); Sleep(1000); } } } _tprintf(_T("%#x\n"), status); return status; }
更多的D3DKMTQueryStatistics调用可以从这里的 gpumon.c代码中进行采样。