2023-12-20 14:45:27 +08:00
|
|
|
#include "gpu_driver_specific.h"
|
2023-10-26 23:28:43 +08:00
|
|
|
|
|
|
|
|
#include "common/library.h"
|
2024-05-21 21:42:57 +08:00
|
|
|
#include "nvml.h"
|
2023-10-26 23:28:43 +08:00
|
|
|
|
|
|
|
|
struct FFNvmlData {
|
|
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetCount_v2)
|
|
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByIndex_v2)
|
2023-10-27 21:05:03 +08:00
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetHandleByPciBusId_v2)
|
2023-10-26 23:28:43 +08:00
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetPciInfo_v3)
|
|
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetTemperature)
|
2023-10-28 13:12:04 +08:00
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetMemoryInfo_v2)
|
|
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetNumGpuCores)
|
2024-04-21 19:07:42 +08:00
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo)
|
2024-07-31 23:40:25 +08:00
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates)
|
2024-01-04 18:50:38 +08:00
|
|
|
FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand)
|
2023-10-26 23:28:43 +08:00
|
|
|
|
|
|
|
|
bool inited;
|
|
|
|
|
} nvmlData;
|
|
|
|
|
|
2023-12-20 14:45:27 +08:00
|
|
|
const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResult result, const char* soName)
|
2023-10-26 23:28:43 +08:00
|
|
|
{
|
2024-05-24 14:40:14 +08:00
|
|
|
#ifndef FF_DISABLE_DLOPEN
|
|
|
|
|
|
2023-10-26 23:28:43 +08:00
|
|
|
if (!nvmlData.inited)
|
|
|
|
|
{
|
|
|
|
|
nvmlData.inited = true;
|
2023-11-01 00:07:23 +08:00
|
|
|
FF_LIBRARY_LOAD(libnvml, NULL, "dlopen nvml failed", soName , 1);
|
2023-10-26 23:28:43 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlInit_v2)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libnvml, nvmlShutdown)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetCount_v2)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByIndex_v2)
|
2023-10-27 21:05:03 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetHandleByPciBusId_v2)
|
2023-10-26 23:28:43 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetPciInfo_v3)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetTemperature)
|
2023-10-28 13:12:04 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMemoryInfo_v2)
|
|
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetNumGpuCores)
|
2024-04-21 19:07:42 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo)
|
2024-07-31 23:40:25 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates)
|
2024-01-04 18:50:38 +08:00
|
|
|
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand)
|
2023-10-26 23:28:43 +08:00
|
|
|
|
|
|
|
|
if (ffnvmlInit_v2() != NVML_SUCCESS)
|
|
|
|
|
{
|
2023-10-28 13:12:04 +08:00
|
|
|
nvmlData.ffnvmlDeviceGetNumGpuCores = NULL;
|
2023-10-26 23:28:43 +08:00
|
|
|
return "nvmlInit_v2() failed";
|
|
|
|
|
}
|
|
|
|
|
atexit((void*) ffnvmlShutdown);
|
|
|
|
|
libnvml = NULL; // don't close nvml
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-28 13:12:04 +08:00
|
|
|
if (nvmlData.ffnvmlDeviceGetNumGpuCores == NULL)
|
2023-10-26 23:28:43 +08:00
|
|
|
return "loading nvml library failed";
|
|
|
|
|
|
2023-10-27 21:05:03 +08:00
|
|
|
nvmlDevice_t device = NULL;
|
2023-12-20 14:45:27 +08:00
|
|
|
if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID)
|
2023-10-27 21:05:03 +08:00
|
|
|
{
|
2023-12-20 14:45:27 +08:00
|
|
|
char pciBusIdStr[32];
|
|
|
|
|
snprintf(pciBusIdStr, sizeof(pciBusIdStr) - 1, "%04x:%02x:%02x.%d", cond->pciBusId.domain, cond->pciBusId.bus, cond->pciBusId.device, cond->pciBusId.func);
|
|
|
|
|
|
|
|
|
|
nvmlReturn_t ret = nvmlData.ffnvmlDeviceGetHandleByPciBusId_v2(pciBusIdStr, &device);
|
2023-10-27 21:05:03 +08:00
|
|
|
if (ret != NVML_SUCCESS)
|
|
|
|
|
return "nvmlDeviceGetHandleByPciBusId_v2() failed";
|
|
|
|
|
}
|
2023-12-20 14:45:27 +08:00
|
|
|
else if (cond->type & FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID)
|
2023-10-26 23:28:43 +08:00
|
|
|
{
|
2023-10-27 21:05:03 +08:00
|
|
|
uint32_t count;
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetCount_v2(&count) != NVML_SUCCESS)
|
|
|
|
|
return "nvmlDeviceGetCount_v2() failed";
|
2023-10-26 23:28:43 +08:00
|
|
|
|
2023-10-27 21:05:03 +08:00
|
|
|
for (uint32_t i = 0; i < count; i++, device = NULL)
|
|
|
|
|
{
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetHandleByIndex_v2(i, &device) != NVML_SUCCESS)
|
|
|
|
|
continue;
|
2023-10-26 23:28:43 +08:00
|
|
|
|
2023-10-27 21:05:03 +08:00
|
|
|
nvmlPciInfo_t pciInfo;
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetPciInfo_v3(device, &pciInfo) != NVML_SUCCESS)
|
|
|
|
|
continue;
|
2023-10-26 23:28:43 +08:00
|
|
|
|
2023-12-20 14:45:27 +08:00
|
|
|
if (pciInfo.pciDeviceId != ((cond->pciDeviceId.deviceId << 16u) | cond->pciDeviceId.vendorId) ||
|
|
|
|
|
pciInfo.pciSubSystemId != cond->pciDeviceId.subSystemId)
|
2023-10-27 21:05:03 +08:00
|
|
|
continue;
|
2023-10-26 23:28:43 +08:00
|
|
|
|
2023-10-27 21:05:03 +08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!device) return "Device not found";
|
2023-10-26 23:28:43 +08:00
|
|
|
}
|
|
|
|
|
|
2024-01-04 18:50:38 +08:00
|
|
|
nvmlBrandType_t brand;
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetBrand(device, &brand) == NVML_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
switch (brand)
|
|
|
|
|
{
|
|
|
|
|
case NVML_BRAND_NVIDIA_RTX:
|
|
|
|
|
case NVML_BRAND_QUADRO_RTX:
|
|
|
|
|
case NVML_BRAND_GEFORCE:
|
|
|
|
|
case NVML_BRAND_TITAN:
|
|
|
|
|
case NVML_BRAND_TESLA:
|
|
|
|
|
case NVML_BRAND_QUADRO:
|
|
|
|
|
*result.type = FF_GPU_TYPE_DISCRETE;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-28 13:12:04 +08:00
|
|
|
if (result.temp)
|
|
|
|
|
{
|
|
|
|
|
uint32_t value;
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetTemperature(device, NVML_TEMPERATURE_GPU, &value) == NVML_SUCCESS)
|
|
|
|
|
*result.temp = value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result.memory)
|
|
|
|
|
{
|
|
|
|
|
nvmlMemory_v2_t memory = { .version = nvmlMemory_v2 };
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetMemoryInfo_v2(device, &memory) == NVML_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
result.memory->total = memory.used + memory.free;
|
|
|
|
|
result.memory->used = memory.used;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (result.coreCount)
|
|
|
|
|
nvmlData.ffnvmlDeviceGetNumGpuCores(device, result.coreCount);
|
2023-10-27 21:05:03 +08:00
|
|
|
|
2023-12-20 14:45:27 +08:00
|
|
|
if (result.frequency)
|
2024-07-17 14:52:35 +08:00
|
|
|
nvmlData.ffnvmlDeviceGetMaxClockInfo(device, NVML_CLOCK_GRAPHICS, result.frequency);
|
2023-12-20 14:45:27 +08:00
|
|
|
|
2024-08-01 13:54:03 +08:00
|
|
|
if (result.coreUsage)
|
2024-07-31 23:40:25 +08:00
|
|
|
{
|
2024-08-01 13:54:03 +08:00
|
|
|
nvmlUtilization_t utilization;
|
|
|
|
|
if (nvmlData.ffnvmlDeviceGetUtilizationRates(device, &utilization) == NVML_SUCCESS)
|
|
|
|
|
*result.coreUsage = utilization.gpu;
|
2024-07-31 23:40:25 +08:00
|
|
|
}
|
|
|
|
|
|
2023-10-27 21:05:03 +08:00
|
|
|
return NULL;
|
2024-05-24 14:40:14 +08:00
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
|
|
FF_UNUSED(cond, result, soName);
|
|
|
|
|
return "dlopen is disabled";
|
|
|
|
|
|
|
|
|
|
#endif
|
2023-10-26 23:28:43 +08:00
|
|
|
}
|