检测没有CUDA的NVIDIA GPU

我想提取一组有关NVIDIA GPU的信息,而不需要链接到CUDA库。 唯一需要的信息是计算能力和GPU的名称,这可能比这更有用但不是必需的。 代码应该用C(或C ++)编写。 这些信息将在配置时(当CUDA工具包不可用时)和运行时(当执行的二进制文件未使用CUDA支持编译时)使用,以向用户建议系统中存在受支持的GPU。

据我所知,这可以通过驱动程序API实现,但我不太熟悉这需要的技术细节。 所以我的问题是:

  • 至少满足最低要求的具体步骤是什么(见上文);

  • 有没有这样的开源代码?

请注意,我的第一步是为Linux提供一些代码,但最终我需要与平台无关的代码。 考虑到CUDA的平台可用性,对于完整的解决方案,这将涉及用于Linux,Mac OS和Windows的x86 / AMD64的代码(至少目前,该列表可以很快通过ARM扩展)。

编辑

我的意思是“它可以通过驱动程序API”是一个应该能够动态加载libcuda.so并通过驱动程序API查询设备属性。 不过,我不确定细节。

不幸的是,NVML不提供有关设备计算能力的信息。

你需要做的是:

  1. 手动加载CUDA库(应用程序未链接到libcuda)
    • 如果库不存在,则不安装CUDA驱动程序
  2. 查找库中必要函数的指针
  3. 使用驱动程序API查询有关可用GPU的信息

我希望这段代码会有所帮助。 我已经在Linux下进行了测试,但只需稍作修改,它也应该在Windows下编译。

#include  #include  #ifdef WINDOWS #include  #else #include  #endif void * loadCudaLibrary() { #ifdef WINDOWS return LoadLibraryA("nvcuda.dll"); #else return dlopen ("libcuda.so", RTLD_NOW); #endif } void (*getProcAddress(void * lib, const char *name))(void){ #ifdef WINDOWS return (void (*)(void)) GetProcAddress(lib, name); #else return (void (*)(void)) dlsym(lib,(const char *)name); #endif } int freeLibrary(void *lib) { #ifdef WINDOWS return FreeLibrary(lib); #else return dlclose(lib); #endif } typedef CUresult CUDAAPI (*cuInit_pt)(unsigned int Flags); typedef CUresult CUDAAPI (*cuDeviceGetCount_pt)(int *count); typedef CUresult CUDAAPI (*cuDeviceComputeCapability_pt)(int *major, int *minor, CUdevice dev); int main() { void * cuLib; cuInit_pt my_cuInit = NULL; cuDeviceGetCount_pt my_cuDeviceGetCount = NULL; cuDeviceComputeCapability_pt my_cuDeviceComputeCapability = NULL; if ((cuLib = loadCudaLibrary()) == NULL) return 1; // cuda library is not present in the system if ((my_cuInit = (cuInit_pt) getProcAddress(cuLib, "cuInit")) == NULL) return 1; // sth is wrong with the library if ((my_cuDeviceGetCount = (cuDeviceGetCount_pt) getProcAddress(cuLib, "cuDeviceGetCount")) == NULL) return 1; // sth is wrong with the library if ((my_cuDeviceComputeCapability = (cuDeviceComputeCapability_pt) getProcAddress(cuLib, "cuDeviceComputeCapability")) == NULL) return 1; // sth is wrong with the library { int count, i; if (CUDA_SUCCESS != my_cuInit(0)) return 1; // failed to initialize if (CUDA_SUCCESS != my_cuDeviceGetCount(&count)) return 1; // failed for (i = 0; i < count; i++) { int major, minor; if (CUDA_SUCCESS != my_cuDeviceComputeCapability(&major, &minor, i)) return 1; // failed printf("dev %d CUDA compute capability major %d minor %d\n", i, major, minor); } } freeLibrary(cuLib); return 0; } 

在Linux上测试:

 $ gcc -ldl main.c $ ./a.out dev 0 CUDA compute capability major 2 minor 0 dev 1 CUDA compute capability major 2 minor 0 

在没有CUDA驱动程序的情况下测试linux

 $ ./a.out $ echo $? 1 

干杯

当然这些人都知道答案:

http://www.ozone3d.net/gpu_caps_viewer

但我只能知道我可以安装CUDA或OpenCL。

我认为一种方法可能是直接使用OpenGL,也许这就是你所说的驱动程序API,但我只能给你这些例子(需要CUDA):

http://www.naic.edu/~phil/hardware/nvidia/doc/src/deviceQuery/deviceQuery.cpp

首先,我认为NVIDIA NVML是您正在寻找的API。 其次,有一个基于NVML的开源项目叫做PAPI NVML 。

我通过静态使用和链接CUDA 6.0 SDK解决了这个问题。 它生成的应用程序也适用于没有NVIDIA卡的机器或未安装SDK的机器。 在这种情况下,它将指示没有CUDAfunction的设备。

CUDA SDK calld deviceQuery附带的示例中有一个示例 – 我使用它的代码片段来编写以下代码。 我决定是否存在支持CUDA的设备,如果存在,则具有最高的计算能力:

 #include  struct GpuCap { bool QueryFailed; // True on error int DeviceCount; // Number of CUDA devices found int StrongestDeviceId; // ID of best CUDA device int ComputeCapabilityMajor; // Major compute capability (of best device) int ComputeCapabilityMinor; // Minor compute capability }; GpuCap GetCapabilities() { GpuCap gpu; gpu.QueryFailed = false; gpu.StrongestDeviceId = -1; gpu.ComputeCapabilityMajor = -1; gpu.ComputeCapabilityMinor = -1; cudaError_t error_id = cudaGetDeviceCount(&gpu.DeviceCount); if (error_id != cudaSuccess) { gpu.QueryFailed = true; gpu.DeviceCount = 0; return gpu; } if (gpu.DeviceCount == 0) return gpu; // "There are no available device(s) that support CUDA // Find best device for (int dev = 0; dev < gpu.DeviceCount; ++dev) { cudaDeviceProp deviceProp; cudaGetDeviceProperties(&deviceProp, dev); if (deviceProp.major > gpu.ComputeCapabilityMajor) { gpu.ComputeCapabilityMajor = dev; gpu.ComputeCapabilityMajor = deviceProp.major; gpu.ComputeCapabilityMinor = 0; } if (deviceProp.minor > gpu.ComputeCapabilityMinor) { gpu.ComputeCapabilityMajor = dev; gpu.ComputeCapabilityMinor = deviceProp.minor; } } return gpu; }