Reputation: 786
I have a temperature monitor program I wrote a while back which monitors the temperatures and fans on my AMD Graphics cards, checking for fan failure OR overheats. The problem with it, is that it needs to know in advance which process will be using the GPU(Graphics Processing Unit), in order to kill it or gracefully make it stop to avoid overheating.
To make my program more dynamic, I needed a way to find which process is using the GPU, much like which process is using CPU time(Task Manager). One such application is Process Explorer from SysInternals.
I am asking, how may I do this in Windows in C? I am aware that if there is such a way, it would target Vista and above.
Upvotes: 6
Views: 6053
Reputation: 3399
You would need to call somewhat undocumented direct3d API function D3DKMTQueryStatistics.
Sample code taken from ProcessHacker forum:
#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;
}
More calls to D3DKMTQueryStatistics can be sampled from gpumon.c code here.
Upvotes: 0
Reputation: 2060
If you have a Tesla board or high-end Quadro and running on Windows Server 2008 R2 64bit, Windows 7 64bit (or 32/64bit Linux) then you can use NVML to do that.
Download latest NVML SDK (Tespla Deployment Kit) and take a look at these two functions:
nvmlReturn_t nvmlDeviceGetComputeRunningProcesses (nvmlDevice_t device,
unsigned int infoCount,
nvmlProcessInfo_t * infos)
nvmlReturn_t nvmlDeviceGetTemperature (nvmlDevice_t device,
nvmlTemperatureSensors_t sensorType,
unsigned int * temp)
Watch out for:
nvmlReturn_t nvmlDeviceGetFanSpeed (nvmlDevice_t device, unsigned int * speed)
It "retrieves the intended operating speed of the device’s fan" not real fan speed. So you can't use it for checking fan failures.
I'm not aware of nvmlDeviceGetComputeRunningProcesses replacement that'd work on GeForce boards, but Windows NvAPI (which also works on GeForce) allows to query both Fan Speed and Temperature.
Upvotes: 2