我遇到了CUDA 6.0统一内存的问题;对于某些对象,可以从CUDA内核访问成员变量,但成员函数不是(并且尝试使用它们会导致内存访问冲突)。我基本上将C ++项目移植到CUDA并使用命名空间来保存实际的CUDA内核。
有一个名为“Managed”的类,它是需要在CPU和GPU内存空间之间移动的所有类的父类。该类替换了CUDA 6.0 parallel forall blog post中描述的new和delete运算符。它看起来像这样:
#include "Managed.h"
// Overrides new operator
// Used to have "new" create Unified CUDA Host/Device pointers
// This makes memory management a lot easier
__host__ __device__ void* Managed::operator new(size_t len)
{
void *ptr;
cudaMallocManaged(&ptr, len);
return ptr;
}// end operator new
// Overrides delete operator
__host__ __device__ void Managed::operator delete(void* ptr)
{
cudaFree(ptr);
}
__host__ __device__ Managed::Managed()
{
}
__host__ __device__ Managed::~Managed()
{
}
有一个类World
,其中包含一些成员变量和函数。此类的实例在CPU上进行了修改并在GPU上使用,因此它扩展了Managed
。标题World.h
的一部分如下所示:
class World:
public Managed,
public IntersectableContainer
{
public:
__host__ __device__ World();
__host__ __device__ ~World();
int light_count;//<-This was private, but I moved it to public temporarily
__host__ __device__ int getLightCount() const;
[...]
private:
[...]
成员函数getLightCount()如下所示:
// Return number of lights in scene
__host__ __device__ int World::getLightCount() const
{
return light_count;
}
最后,CUDA内核位于名为GPGPUCam的命名空间中。内核从类Window
启动,该类具有指向Camera
和World
的指针。内核能够访问World
成员变量,但无法使用任何成员函数。这是内核:
// Cuda rendering kernel
__global__ void GPGPUCam::CUDARenderScene(World* const world, Camera* const camera, uchar4* target, int width)
{
int x = (blockIdx.x * blockDim.x) + threadIdx.x;
int y = (blockIdx.y * blockDim.y) + threadIdx.y;
int lc = world->light_count;//<-Works fine (tested in debugger)
lc = world->getLightCount();//<-Memory access violation happens here
}
这是CUDA内存检查器的输出。我运行1个块和1个线程/块来减少输出的长度,这就是为什么只有1个访问冲突。
Summary of access violations:
[...]\gpgpucam.cu(31):error MemoryChecker: #misaligned=0 #invalidAddress=1
================================================================================
Memory Checker detected 1 access violations.
error = access violation on load (global memory)
gridid = 8
blockIdx = {0,0,0}
threadIdx = {0,0,0}
address = 0x13ff44ef0
accessSize = 8
奇怪的是,Camera
也扩展了Managed
,我可以从同一个内核访问其成员函数。
每个源文件以.h(标题)或.cu(C ++ / CUDA文件)结尾,每个.cu文件在Visual Studio属性页中设置为CUDA C / C ++文件,因此使用{{ 1}}。
NVCC 6.5.13版,Visual Studio 2013
我希望在没有粘贴整个项目的情况下,我已经提供了足够的信息。谢谢你的帮助!