【问题标题】:NvCplGetThermalSettings call to nvcpl.dll returns false (C++)对 nvcpl.dll 的 NvCplGetThermalSettings 调用返回 false (C++)
【发布时间】:2014-09-24 13:22:17
【问题描述】:

我正在尝试使用下面的代码(不是我的;稍作修改)检索 GPU 温度信息,但是当我尝试调用 .dll 函数 nvCplGetThermalSettings 时得到“错误”返回:

HINSTANCE lib = LoadLibraryA("nvcpl.dll");
if(lib)
{
    NvCplGetThermalSettings nvCplGetThermalSettings = reinterpret_cast<NvCplGetThermalSettings> (GetProcAddress(lib,"NvCplGetThermalSettings"));
    DWORD coreTemp,ambientTemp,upperLimit;
    int success = nvCplGetThermalSettings(0,&coreTemp,&ambientTemp,&upperLimit);
    if(!success) {
        printf("Call failed: %d\n", success);
    }
    else {
        char text[128];
        printf(
            "Core Temp:    %d°\n"
            "Ambient Temp:    %d°\n"
            "Upper Limit:    %d°",coreTemp,ambientTemp,upperLimit);
    }
    FreeLibrary(lib);
}
else {
     printf("Couldn't load library.\n");
}

.dll 正在加载,相对是最新的(2013 年),GPU-Z 等应用程序能够显示此信息,所以我知道这不是硬件/驱动程序问题。任何想法都提前表示赞赏。

【问题讨论】:

    标签: c++ winapi dll gpu temperature


    【解决方案1】:

    如果其他人对该解决方案感兴趣,使用 nvapi64.dll 可以解决问题,但需要使用非 API 特定的对象复制一些结构,并且需要对标头进行一些挖掘。功能代码如下:

    #include <windows.h>
    #include <iostream>
    #define NVAPI_MAX_THERMAL_SENSORS_PER_GPU 3
    typedef enum 
    {
        NVAPI_THERMAL_TARGET_NONE          = 0,
        NVAPI_THERMAL_TARGET_GPU           = 1,     //!< GPU core temperature requires NvPhysicalGpuHandle
        NVAPI_THERMAL_TARGET_MEMORY        = 2,     //!< GPU memory temperature requires NvPhysicalGpuHandle
        NVAPI_THERMAL_TARGET_POWER_SUPPLY  = 4,     //!< GPU power supply temperature requires NvPhysicalGpuHandle
        NVAPI_THERMAL_TARGET_BOARD         = 8,     //!< GPU board ambient temperature requires NvPhysicalGpuHandle
        NVAPI_THERMAL_TARGET_VCD_BOARD     = 9,     //!< Visual Computing Device Board temperature requires NvVisualComputingDeviceHandle
        NVAPI_THERMAL_TARGET_VCD_INLET     = 10,    //!< Visual Computing Device Inlet temperature requires NvVisualComputingDeviceHandle
        NVAPI_THERMAL_TARGET_VCD_OUTLET    = 11,    //!< Visual Computing Device Outlet temperature requires NvVisualComputingDeviceHandle
    
        NVAPI_THERMAL_TARGET_ALL           = 15,
        NVAPI_THERMAL_TARGET_UNKNOWN       = -1,
    } NV_THERMAL_TARGET;
    
    typedef struct
    {
        int   version;                //!< structure version 
        int   count;                  //!< number of associated thermal sensors
        struct 
        {
            int       controller;        //!< internal, ADM1032, MAX6649...
            int                       defaultMinTemp;    //!< The min default temperature value of the thermal sensor in degree Celsius 
            int                       defaultMaxTemp;    //!< The max default temperature value of the thermal sensor in degree Celsius 
            int                       currentTemp;       //!< The current temperature value of the thermal sensor in degree Celsius 
            NV_THERMAL_TARGET           target;            //!< Thermal sensor targeted @ GPU, memory, chipset, powersupply, Visual Computing Device, etc.
        } sensor[NVAPI_MAX_THERMAL_SENSORS_PER_GPU];
    
    } NV_GPU_THERMAL_SETTINGS;
    
    // magic numbers, do not change them
    #define NVAPI_MAX_PHYSICAL_GPUS   64
    #define NVAPI_MAX_USAGES_PER_GPU  34
    
    // function pointer types
    typedef int *(*NvAPI_QueryInterface_t)(unsigned int offset);
    typedef int (*NvAPI_Initialize_t)();
    typedef int (*NvAPI_EnumPhysicalGPUs_t)(int **handles, int *count);
    typedef int (*NvAPI_GPU_GetUsages_t)(int *handle, unsigned int *usages);
    typedef int (*NvAPI_GPU_GetThermalSettings_t)(int *handle, int sensorIndex, NV_GPU_THERMAL_SETTINGS *temp);
    
    int main()
    {   
        HMODULE hmod = LoadLibraryA("nvapi64.dll");
        if (hmod == NULL)
        {
            std::cerr << "Couldn't find nvapi.dll" << std::endl;
            return 1;
        }
    
        // nvapi.dll internal function pointers
        NvAPI_QueryInterface_t      NvAPI_QueryInterface     = NULL;
        NvAPI_Initialize_t          NvAPI_Initialize         = NULL;
        NvAPI_EnumPhysicalGPUs_t    NvAPI_EnumPhysicalGPUs   = NULL;
        NvAPI_GPU_GetUsages_t       NvAPI_GPU_GetUsages      = NULL;
        NvAPI_GPU_GetThermalSettings_t  NvAPI_GPU_GetThermalSettings = NULL;
    
        // nvapi_QueryInterface is a function used to retrieve other internal functions in nvapi.dll
        NvAPI_QueryInterface = (NvAPI_QueryInterface_t) GetProcAddress(hmod, "nvapi_QueryInterface");
    
        // some useful internal functions that aren't exported by nvapi.dll
        NvAPI_Initialize = (NvAPI_Initialize_t) (*NvAPI_QueryInterface)(0x0150E828);
        NvAPI_EnumPhysicalGPUs = (NvAPI_EnumPhysicalGPUs_t) (*NvAPI_QueryInterface)(0xE5AC921F);
        NvAPI_GPU_GetUsages = (NvAPI_GPU_GetUsages_t) (*NvAPI_QueryInterface)(0x189A1FDF);
        NvAPI_GPU_GetThermalSettings = (NvAPI_GPU_GetThermalSettings_t) (*NvAPI_QueryInterface)(0xE3640A56);
    
        if (NvAPI_Initialize == NULL || NvAPI_EnumPhysicalGPUs == NULL ||
            NvAPI_EnumPhysicalGPUs == NULL || NvAPI_GPU_GetUsages == NULL)
        {
            std::cerr << "Couldn't get functions in nvapi.dll" << std::endl;
            return 2;
        }
    
        // initialize NvAPI library, call it once before calling any other NvAPI functions
        (*NvAPI_Initialize)();
        NV_GPU_THERMAL_SETTINGS          nvgts;
        int          gpuCount = 0;
        int          gpuTemp;
        int         *gpuHandles[NVAPI_MAX_PHYSICAL_GPUS] = { NULL };
        unsigned int gpuUsages[NVAPI_MAX_USAGES_PER_GPU] = { 0 };
    
        // gpuUsages[0] must be this value, otherwise NvAPI_GPU_GetUsages won't work
        gpuUsages[0] = (NVAPI_MAX_USAGES_PER_GPU * 4) | 0x10000;
    
        (*NvAPI_EnumPhysicalGPUs)(gpuHandles, &gpuCount);
        nvgts.version = sizeof(NV_GPU_THERMAL_SETTINGS) | (1<<16);
        nvgts.count = 0;
        nvgts.sensor[0].controller = -1;
        nvgts.sensor[0].target = NVAPI_THERMAL_TARGET_GPU;
    
        // print GPU usage every second
        for (int i = 0; i < 100; i++)
        {
            (*NvAPI_GPU_GetThermalSettings)(gpuHandles[0], 0 ,&nvgts);
            printf("%d\n", nvgts.sensor[0].currentTemp);
            (*NvAPI_GPU_GetUsages)(gpuHandles[0], gpuUsages);
            int usage = gpuUsages[3];
            std::cout << "GPU Usage: " << usage << std::endl;
            Sleep(1000);
        }
    
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-11-11
      • 2023-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-19
      • 1970-01-01
      • 2018-05-17
      • 1970-01-01
      相关资源
      最近更新 更多