CUDA,OpenGL互操作:在cudaGraphicsGLRegisterBuffer上出现cudaErrorMemoryAllocation错误

8
我在使用 cudaGraphicsGLRegisterBuffer() 时遇到了随机的CUDA内存分配错误。我有一个相当大的OpenGL PBO对象,它与CUDA共享。PBO对象的创建方式如下:
GLuint          buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
glBufferData(target, rows * cols * 4, NULL, GL_DYNAMIC_COPY);
glUnmapBuffer(_target);
glBindBuffer(_target, 0);

这个对象相当大,宽度和高度都是5000。然而,在我的GPU上分配得很好。现在,我将其在OpenGL和CUDA之间共享,如下所示。我有一个简单的类来管理它:

class CudaPBOGraphicsResource
{
public:
    CudaPBOGraphicsResource(GLuint pbo_id);
    ~CudaPBOGraphicsResource();
     inline cudaGraphicsResource_t resource() const { return _cgr; }
private:
    cudaGraphicsResource_t          _cgr;
};

CudaPBOGraphicsResource::CudaPBOGraphicsResource(GLuint pbo_id)
{
    checkCudaErrors(cudaGraphicsGLRegisterBuffer(&_cgr, pbo_id,
                    cudaGraphicsRegisterFlagsNone));
    checkCudaErrors(cudaGraphicsMapResources(1, &_cgr, 0));
}

CudaPBOGraphicsResource::~CudaPBOGraphicsResource()
{
    if (_cgr) {
        checkCudaErrors(cudaGraphicsUnmapResources(1, &_cgr, 0));
    }
}

现在我将OpenGL和CUDA互操作性如下:

{
    CudaPBOGraphicsResource input_cpgr(pbo_id);
    uchar4 * input_ptr = 0;
    size_t num_bytes;
    checkCudaErrors(cudaGraphicsResourceGetMappedPointer((void 
                    **)&input_ptr, &num_bytes,
                    input_cpgr.resource()));

    call_my_kernel(input_ptr);
}

这个程序在我输入一段时间后会崩溃,出现以下错误:

CUDA error code=2(cudaErrorMemoryAllocation) 
                 "cudaGraphicsGLRegisterBuffer(&_cgr, pbo_id, 
                  cudaGraphicsRegisterFlagsNone)" 
Segmentation fault

我不确定为什么会出现内存分配,因为我认为这是共享的。在调用内核后,我添加了cudaDeviceSynchronize(),但错误仍然存在。我的call_my_kernel()函数现在几乎什么也没做,所以没有其他CUDA调用会引发此错误!

我正在使用Cuda 7和K4000 Quadro卡在Linux上。

编辑 我将驱动程序更新到最新的346.72版本,但错误仍然存在。它也与内核调用无关。只是调用cudaGraphicsGLRegisterBuffer()似乎会在GPU上泄漏内存。在程序运行时运行nvidia-smi显示内存稳步增加。我仍然不知道为什么会发生任何复制...

1个回答

7

好的,我找到了解决我的难题的答案,希望这会对使用CUDA-OGL的其他人有所帮助。

问题在于我调用了以下代码:

checkCudaErrors(cudaGraphicsGLRegisterBuffer(&_cgr, pbo_id,
                cudaGraphicsRegisterFlagsNone));

每次调用实际上只需要调用一次,然后我只需要在_cgr对象上调用map/unmap。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接