2012-10-22 20 views
5

Ho un programma di monitoraggio della temperatura che ho scritto un po 'indietro che monitora le temperature e i fan delle mie schede grafiche AMD, controllando l'eventuale guasto della ventola o il surriscaldamento. Il problema con esso, è che ha bisogno di sapere in anticipo quale processo utilizzerà la GPU (unità di elaborazione grafica), al fine di ucciderlo o farlo smettere con grazia per evitare il surriscaldamento.Come si ottiene l'utilizzo della GPU per processo?

Per rendere il mio programma più dinamico, avevo bisogno di un modo per trovare quale processo sta utilizzando la GPU, in modo molto simile a quale processo sta utilizzando il tempo della CPU (Task Manager). Una di queste applicazioni è Process Explorer di SysInternals.

Mi chiedo, come posso farlo in Windows in C? Sono consapevole del fatto che, se ci fosse un tale modo, avrebbe come target Vista e sopra.

+0

E le applicazioni OpenCL? E la tua domanda è molto specifica del sistema operativo (su Linux, è diversa da quella su Windows). –

+0

Sì, Windows è il sistema operativo che sto prendendo di mira. E che dire delle applicazioni OpenCL? È infatti a causa di OpenCL che ho inizialmente scritto la mia applicazione, quindi la mia GPU/s non si surriscalda. – farmdve

+0

Solo un breve suggerimento: guarda [Process Hacker] (http://superuser.com/a/585597/297281) C [codice sorgente] (https://github.com/processhacker2/processhacker2/search?utf8=% E2% 9C% 93 & q = gpu); sembra che le chiamate API statistiche dirette 3d vengano utilizzate lì. –

risposta

1

Se si dispone di una scheda Tesla o di fascia alta Quadro e in esecuzione su Windows Server 2008 R2 64bit , Windows 7 a 64 bit (o 32/64bit Linux) è possibile utilizzare NVML per farlo.

Scarica ultima NVML SDK (Tespla Deployment Kit) e dare un'occhiata a queste due funzioni:

nvmlReturn_t nvmlDeviceGetComputeRunningProcesses (nvmlDevice_t device, 
                unsigned int infoCount, 
                nvmlProcessInfo_t * infos) 

nvmlReturn_t nvmlDeviceGetTemperature (nvmlDevice_t device, 
             nvmlTemperatureSensors_t sensorType, 
             unsigned int * temp) 

Attenzione per:

nvmlReturn_t nvmlDeviceGetFanSpeed (nvmlDevice_t device, unsigned int * speed) 

It "recupera la velocità di funzionamento previsto del ventilatore del dispositivo" non reale della velocità del ventilatore . Quindi non puoi usarlo per controllare i guasti dei fan.

Non sono a conoscenza della sostituzione di nvmlDeviceGetComputeRunningProcesses che funzionerebbe su schede GeForce, ma Windows NvAPI (che funziona anche su GeForce) consente di interrogare sia la velocità della ventola che la temperatura.

0

È necessario chiamare in qualche modo la funzione API direct3d non documentata D3DKMTQueryStatistics.

codice di esempio preso da 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; 
} 

più chiamate a D3DKMTQueryStatistics può essere campionato dal codice gpumon.c here.