带有 OpenGL 的 CUDA:所有支持 CUDA 的设备都忙或不可用

CUDA with OpenGL: all CUDA-capable devices are busy or unavailable

我正在按照 CUDA 示例教程设置 OpenGL,以便与 CUDA 进行图形互操作。 Here is what I'm following。当我开始使用 CUDA 运行time 将缓冲区注册为图形资源和 运行 代码时,我收到一条错误消息,指出所有支持 CUDA 的设备都忙或不可用。

我可以运行其他CUDA代码没问题。如果我不尝试进行互操作,我可以使用 OpenGL 渲染图形(这样我就可以:将内存交换到 CPU,在 OpenGL 中渲染,等等)。

我认为 CUDA 设备此时没有做任何事情。我已经尝试关闭所有其他 windows 以查看是否有其他东西正在使用该资源,但这并没有改变任何东西。这是我到目前为止展示的初始化过程的一小段代码:

#include "common/gl_helper.h"
#include "cuda.h"
#include "cuda_gl_interop.h"    
#include "common/book.h"

#define DIM 1024

PFNGLBINDBUFFERARBPROC    glBindBuffer     = NULL;
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers  = NULL;
PFNGLGENBUFFERSARBPROC    glGenBuffers     = NULL;
PFNGLBUFFERDATAARBPROC    glBufferData     = NULL;

GLuint bufferObj;
cudaGraphicsResource *resource;

int main( void ) {
    cudaDeviceProp prop;
    int dev;    

    int c=1;
    char* dummy = "";
    glutInit( &c, &dummy );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA );
    glutInitWindowSize( DIM, DIM );
    glutCreateWindow( "bitmap" );

    glBindBuffer    = (PFNGLBINDBUFFERARBPROC)GET_PROC_ADDRESS("glBindBuffer");
    glDeleteBuffers = (PFNGLDELETEBUFFERSARBPROC)GET_PROC_ADDRESS("glDeleteBuffers");
    glGenBuffers    = (PFNGLGENBUFFERSARBPROC)GET_PROC_ADDRESS("glGenBuffers");
    glBufferData    = (PFNGLBUFFERDATAARBPROC)GET_PROC_ADDRESS("glBufferData");

    glGenBuffers(1, &bufferObj);
    glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, bufferObj);
    glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, DIM*DIM*4, NULL, GL_DYNAMIC_DRAW_ARB);

    memset(&prop, 0, sizeof(cudaDeviceProp));
    prop.major = 1;
    prop.minor = 0;
    HANDLE_ERROR(cudaChooseDevice(&dev, &prop));
    HANDLE_ERROR(cudaGLSetGLDevice(dev));

    HANDLE_ERROR(cudaGraphicsGLRegisterBuffer(&resource, bufferObj, cudaGraphicsRegisterFlagsWriteDiscard));
}

最后一行是 returns 错误。 common/ 文件来自 CUDA-by-example 书籍文件,如果您愿意,我可以 post 它们。我也只是尝试 运行ning 书籍文件中的示例(据说是工作代码),但我仍然遇到同样的问题。我需要做什么来解决这个问题?

系统信息:Windows 7 x64,Visual Studio 2010,带有 CUDA 6.5。我有 GTX650 显卡。

我已经尝试了 Nvidia 提供的测试样本和 none 互操作的工作。即使对于我没有写的代码。此代码适用于我的笔记本电脑,其中装有 GTX750M。

在 CUDA 识别支持 ​​OpenGL 的设备之前,您必须创建一个 OpenGL 上下文。 glutCreateWindows 是在使用 GLUT 时创建 OpenGL 上下文的原因。

鉴于 CUDA 安装(可在 ProgramData/Nvidia Corporation/Examples 中找到)提供的示例无法使用互操作,问题不在于代码,而在于计算机的配置。为了更好地衡量,我首先卸载了所有旧的 CUDA 版本并重新安装了 CUDA 7.0。那没有解决任何问题,所以我继续前进。

本例中的问题是由以下原因引起的:

我把显示器插在主板上,用集成显卡显示,因为在Linux,如果显示和计算是同一个设备,CUDA是无法调试的。我切换到 Windows,忘记将显示器换回 GPU。当我 运行 我的代码时,cudaGLSetGLDevice 使用了专用 GPU,这符合预期。然而,OpenGL 由专用显卡处理,因为那是用于显示的。因此,当我尝试使用 cudaGraphicsGLRegisterBuffer 注册互操作时,使用了集成显卡。由于我的集成卡不支持 CUDA,因此它抛出了没有可用 CUDA 设备的错误。

解决办法?出色地: 重新启动计算机并进入 BIOS(不要交换显示器)。在 BIOS 中确保图形设置为使用专用 GPU(在我的例子中是 PCIe 设置)。将显示器插入 GPU 的视频端口。在 Nvidia 驱动程序开始工作之前,启动计算机会导致一些非常奇怪的显示(我不得不再次重新启动才能让它使用两个显示器)。之后,运行 Nsight 中的示例代码成功了!

我希望能帮助其他偶然发现这个问题的人。