From 96fc1db85e3d2e1636cfcaca85b9debf259f1d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 20 Jun 2024 11:08:26 +0800 Subject: [PATCH] OpenCL: detect GPU info --- src/detection/opencl/opencl.c | 111 ++++++++++++++++++++++++---------- src/detection/opencl/opencl.h | 3 +- src/modules/opencl/opencl.c | 64 +++++++++++++++++--- 3 files changed, 135 insertions(+), 43 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index f3339bee8..3e4681f1e 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -11,6 +11,7 @@ #include "common/library.h" #include "common/parsing.h" +#include "detection/gpu/gpu.h" #include "util/stringUtils.h" #include @@ -23,50 +24,94 @@ typedef struct OpenCLData { - FF_LIBRARY_SYMBOL(clGetPlatformIDs) - FF_LIBRARY_SYMBOL(clGetDeviceIDs) + FF_LIBRARY_SYMBOL(clGetPlatformInfo) FF_LIBRARY_SYMBOL(clGetDeviceInfo) + FF_LIBRARY_SYMBOL(clGetDeviceIDs) } OpenCLData; static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) { - cl_platform_id platformID = NULL; - cl_uint numPlatforms = 0; - data->ffclGetPlatformIDs(1, &platformID, &numPlatforms); + char buffer[1024] = ""; + if (data->ffclGetPlatformInfo(NULL, CL_PLATFORM_VERSION, sizeof(buffer), buffer, NULL) != CL_SUCCESS) + return "clGetPlatformInfo(NULL, CL_PLATFORM_VERSION) failed"; - if(numPlatforms == 0) - return "clGetPlatformIDs returned 0 platforms"; + { + const char* versionPretty = buffer; + if(ffStrStartsWithIgnCase(buffer, "OpenCL ")) + versionPretty = buffer + strlen("OpenCL "); + ffStrbufSetS(&result->version, versionPretty); + ffStrbufTrim(&result->version, ' '); + } - cl_device_id deviceID = NULL; - cl_uint numDevices = 0; - data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_GPU, 1, &deviceID, &numDevices); + if (clGetPlatformInfo(NULL, CL_PLATFORM_NAME, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&result->name, buffer); - if(numDevices == 0) - data->ffclGetDeviceIDs(platformID, CL_DEVICE_TYPE_ALL, 1, &deviceID, &numDevices); + if (clGetPlatformInfo(NULL, CL_PLATFORM_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&result->vendor, buffer); - if(numDevices == 0) - return "clGetDeviceIDs returned 0 devices"; + cl_device_id deviceIDs[32]; + cl_uint numDevices = (cl_uint) (sizeof(deviceIDs) / sizeof(deviceIDs[0])); + data->ffclGetDeviceIDs(NULL, CL_DEVICE_TYPE_GPU, numDevices, deviceIDs, &numDevices); - char version[64] = ""; - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(version), version, NULL); - if(!ffStrSet(version)) - return "clGetDeviceInfo returned NULL or empty string"; + for (cl_uint index = 0; index < numDevices; ++index) + { + cl_device_id deviceID = deviceIDs[index]; + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, sizeof(buffer), buffer, NULL) != CL_SUCCESS) + continue; - const char* versionPretty = version; - if(ffStrStartsWithIgnCase(version, "OpenCL ")) - versionPretty = version + strlen("OpenCL "); - ffStrbufSetS(&result->version, versionPretty); - ffStrbufTrim(&result->version, ' '); + FFGPUResult* gpu = ffListAdd(&result->gpus); + ffStrbufInitS(&gpu->name, buffer); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->driver); + ffStrbufInit(&gpu->platformApi); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->type = FF_GPU_TYPE_UNKNOWN; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->deviceId = index + 1; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; - ffStrbufEnsureFree(&result->device, 128); - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_NAME, result->device.allocated, result->device.chars, NULL); - ffStrbufRecalculateLength(&result->device); - ffStrbufTrim(&result->device, ' '); + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + ffStrbufSetS(&gpu->platformApi, buffer); + ffStrbufTrimRight(&gpu->platformApi, ' '); + } + else + ffStrbufSetS(&gpu->platformApi, "OpenCL"); - ffStrbufEnsureFree(&result->vendor, 32); - data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, result->vendor.allocated, result->vendor.chars, NULL); - ffStrbufRecalculateLength(&result->vendor); - ffStrbufTrim(&result->vendor, ' '); + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_VENDOR, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + ffStrbufSetS(&gpu->vendor, buffer); + + if (data->ffclGetDeviceInfo(deviceID, CL_DRIVER_VERSION, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + const char* versionPretty = strchr(buffer, ' '); + if (versionPretty) + ffStrbufSetS(&gpu->driver, versionPretty + 1); + else + ffStrbufSetS(&gpu->driver, buffer); + } + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->coreCount = (int32_t)*(cl_uint*) buffer; + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->frequency = (*(cl_uint*) buffer) / 1000.; + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->type = *(cl_bool*) buffer == CL_TRUE ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_TYPE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + { + if (*(cl_device_local_mem_type*) buffer == CL_LOCAL) + { + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_LOCAL_MEM_SIZE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->dedicated.total = *(cl_ulong*) buffer; + } + } + + if (data->ffclGetDeviceInfo(deviceID, CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(buffer), buffer, NULL) == CL_SUCCESS) + gpu->shared.total = *(cl_ulong*) buffer; + } return NULL; } @@ -85,7 +130,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result) #endif "libOpenCL"FF_LIBRARY_EXTENSION, 1 ); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformIDs); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetPlatformInfo); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceIDs); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(opencl, data, clGetDeviceInfo); @@ -94,7 +139,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result) #elif defined(MACOS_HAS_OPENCL) // FF_HAVE_OPENCL OpenCLData data; - data.ffclGetPlatformIDs = clGetPlatformIDs; + data.ffclGetPlatformInfo = clGetPlatformInfo; data.ffclGetDeviceIDs = clGetDeviceIDs; data.ffclGetDeviceInfo = clGetDeviceInfo; diff --git a/src/detection/opencl/opencl.h b/src/detection/opencl/opencl.h index 5daaacbda..0274b37b4 100644 --- a/src/detection/opencl/opencl.h +++ b/src/detection/opencl/opencl.h @@ -5,8 +5,9 @@ typedef struct FFOpenCLResult { FFstrbuf version; - FFstrbuf device; + FFstrbuf name; FFstrbuf vendor; + FFlist gpus; //List of FFGPUResult, see detection/gpu/gpu.h } FFOpenCLResult; const char* ffDetectOpenCL(FFOpenCLResult* result); diff --git a/src/modules/opencl/opencl.c b/src/modules/opencl/opencl.c index 3a2135185..641122ef1 100644 --- a/src/modules/opencl/opencl.c +++ b/src/modules/opencl/opencl.c @@ -1,6 +1,7 @@ #include "common/printing.h" #include "common/jsonconfig.h" #include "detection/opencl/opencl.h" +#include "detection/gpu/gpu.h" #include "modules/opencl/opencl.h" #include "util/stringUtils.h" @@ -10,8 +11,9 @@ void ffPrintOpenCL(FFOpenCLOptions* options) { FFOpenCLResult opencl; ffStrbufInit(&opencl.version); - ffStrbufInit(&opencl.device); + ffStrbufInit(&opencl.name); ffStrbufInit(&opencl.vendor); + ffListInit(&opencl.gpus, sizeof(FFGPUResult)); const char* error = ffDetectOpenCL(&opencl); @@ -28,14 +30,14 @@ void ffPrintOpenCL(FFOpenCLOptions* options) { FF_PRINT_FORMAT_CHECKED(FF_OPENCL_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_OPENCL_NUM_FORMAT_ARGS, ((FFformatarg[]) { {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.version, "version"}, - {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.device, "device"}, + {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.name, "name"}, {FF_FORMAT_ARG_TYPE_STRBUF, &opencl.vendor, "vendor"}, })); } } ffStrbufDestroy(&opencl.version); - ffStrbufDestroy(&opencl.device); + ffStrbufDestroy(&opencl.name); ffStrbufDestroy(&opencl.vendor); } @@ -78,8 +80,9 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson { FFOpenCLResult opencl; ffStrbufInit(&opencl.version); - ffStrbufInit(&opencl.device); + ffStrbufInit(&opencl.name); ffStrbufInit(&opencl.vendor); + ffListInit(&opencl.gpus, sizeof(FFGPUResult)); const char* error = ffDetectOpenCL(&opencl); @@ -91,21 +94,64 @@ void ffGenerateOpenCLJsonResult(FF_MAYBE_UNUSED FFOpenCLOptions* options, yyjson { yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "version", &opencl.version); - yyjson_mut_obj_add_strbuf(doc, obj, "device", &opencl.device); + yyjson_mut_obj_add_strbuf(doc, obj, "name", &opencl.name); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &opencl.vendor); + + yyjson_mut_val* gpus = yyjson_mut_obj_add_arr(doc, obj, "gpus"); + FF_LIST_FOR_EACH(FFGPUResult, gpu, opencl.gpus) + { + yyjson_mut_val* gpuObj = yyjson_mut_arr_add_obj(doc, gpus); + yyjson_mut_obj_add_str(doc, gpuObj, "type", gpu->type == FF_GPU_TYPE_UNKNOWN ? "Unknown" : gpu->type == FF_GPU_TYPE_INTEGRATED ? "Integrated" : "Discrete"); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "vendor", &gpu->vendor); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "name", &gpu->name); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "driver", &gpu->driver); + yyjson_mut_obj_add_strbuf(doc, gpuObj, "platformApi", &gpu->platformApi); + yyjson_mut_obj_add_int(doc, gpuObj, "coreCount", gpu->coreCount); + yyjson_mut_obj_add_real(doc, gpuObj, "frequency", gpu->frequency); + + yyjson_mut_val* memoryObj = yyjson_mut_obj_add_obj(doc, gpuObj, "memory"); + + { + yyjson_mut_val* dedicatedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "dedicated"); + if (gpu->dedicated.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "total", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "total"); + + if (gpu->dedicated.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, dedicatedMemory, "used", gpu->dedicated.total); + else + yyjson_mut_obj_add_null(doc, dedicatedMemory, "used"); + } + + { + yyjson_mut_val* sharedMemory = yyjson_mut_obj_add_obj(doc, memoryObj, "shared"); + if (gpu->shared.total != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "total", gpu->shared.total); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "total"); + + if (gpu->shared.used != FF_GPU_VMEM_SIZE_UNSET) + yyjson_mut_obj_add_uint(doc, sharedMemory, "used", gpu->shared.used); + else + yyjson_mut_obj_add_null(doc, sharedMemory, "used"); + } + + yyjson_mut_obj_add_uint(doc, gpuObj, "deviceId", gpu->deviceId); + } } ffStrbufDestroy(&opencl.version); - ffStrbufDestroy(&opencl.device); + ffStrbufDestroy(&opencl.name); ffStrbufDestroy(&opencl.vendor); } void ffPrintOpenCLHelpFormat(void) { FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_OPENCL_MODULE_NAME, "{1}", FF_OPENCL_NUM_FORMAT_ARGS, ((const char* []) { - "version - version", - "device - device", - "vendor - vendor" + "Platform version - version", + "Platform name - name", + "Platform vendor - vendor", })); }