CUDA 代码使两个 GPU “忙”

Posted

技术标签:

【中文标题】CUDA 代码使两个 GPU “忙”【英文标题】:CUDA code makes both GPUs "busy" 【发布时间】:2015-12-11 11:38:03 【问题描述】:

我有一台带有 2 个 Nvidia GPU、一个 Tesla 和一个 Gforce 的 PC (Windows 7 x64)。

两者兼有的想法是能够将 Tesla 用于计算,并将 Gforce 用于计算机可能需要的屏幕/openGL 东西。

但是,每当我运行一些 CUDA 代码时,我都无法访问任何具有 webGL 的网络(使用 chrome),因为我的 webGL 是“不可用的”(检查访问 chrome://gpu/)。这仅在运行 CUDA 代码后发生。

我正在使用的代码由 Matlab mex 调用,但不使用任何其他 Matlab 功能,只是 mexErrMsgIdAndTxt 和一些其他 io 代码在 Matlab 和 C 之间包装。 在我的代码中,我有以下代码来选择正确的显卡:

 int deviceCount = 0;
    cudaGetDeviceCount(&deviceCount);
     if (deviceCount == 0)
    
        mexErrMsgIdAndTxt("CBCT:CUDA:Ax:cudaGetDeviceCount","No CUDA enabled NVIDIA GPUs found");
    
    bool found=false;
    for (int dev = 0; dev < deviceCount; ++dev)
    
        cudaSetDevice(dev);
        cudaDeviceProp deviceProp;
        cudaGetDeviceProperties(&deviceProp, dev);

        if (strcmp(deviceProp.name, "Tesla K40c") == 0)
            found=true;
            break;
        
    
    if (!found)
        mexErrMsgIdAndTxt("CBCT:CUDA:Ax:cudaDevice","No Tesla K40c found");

当代码结束时我调用

 cudaDeviceReset();

我的印象是(当然是错误的)这段代码可以确保 Gforce 可以免费供 PC 使用,但事实并非如此。

为什么会这样? 我应该在我的代码中添加什么以确保 Gforce 可以免费用于计算机?

【问题讨论】:

【参考方案1】:

这不是你应该添加的,而是你应该删除的。不要这样做:

for (int dev = 0; dev < deviceCount; ++dev)

    cudaSetDevice(dev);
    cudaDeviceProp deviceProp;
    cudaGetDeviceProperties(&deviceProp, dev);

    if (strcmp(deviceProp.name, "Tesla K40c") == 0)
        found=true;
        break;
    

改为这样做:

for (int dev = 0; dev < deviceCount; ++dev)

    cudaDeviceProp deviceProp;
    cudaGetDeviceProperties(&deviceProp, dev);

    if (strcmp(deviceProp.name, "Tesla K40c") == 0)
        cudaSetDevice(dev);
        found=true;
        break;
    

从 CUDA 4.0 开始,cudaSetDevice() 在设备上建立上下文。因此,仅仅通过寻找正确的 GPU 的行为,您实际上是在初始化一个上下文并使每个设备都忙于 OpenGL。去掉无条件的cudaSetDevice(),问题就会消失(也不需要cudaDeviceReset())。

【讨论】:

确实,就这么简单! 值得注意的是,我从 cudaSamples 中截取了这段代码。他们也应该听从你的建议! 平心而论,cudaDeviceReset 的功能可能随着时间的推移略有变化。文档有点暗示它应该破坏并从设备中弹出上下文,但也许它没有。重要的一点是cudaGetDeviceProperties 不需要(也从来没有)需要上下文才能工作,建立上下文然后尝试销毁它似乎是一个相当糟糕的设计选择,如果你不需要它的替代方案将完全跳过上下文建立。 谢谢!很高兴知道。实际上,在不需要时使用 setDevice() 是一个可怕的设计选择。感谢您的提示;) 您具体指的是哪个 cuda 样本?

以上是关于CUDA 代码使两个 GPU “忙”的主要内容,如果未能解决你的问题,请参考以下文章

两个进程可以共享相同的 GPU 内存吗? (CUDA)

Torch Cuda - 在两个 GPU 内核上生成两个进程

CUDA学习之使用GPU进行两个数相加

CUDA学习之使用GPU进行两个数组相加

如何确保两个流中的两个内核同时发送到 GPU 运行?

如何在cuda中的不同gpu之间复制内存