我有一个简单的程序,它分配一个unsigned __int64
(堆栈上的8个字节),然后尝试使用cudaHostRegister在GPU上注册该内存。程序进行此调用的部分如下所示:
unsigned __int64 mem;
unsigned __int64 *pMem = &mem;
cudaError_t result;
result = cudaHostRegister(pMem, sizeof(unsigned __int64), cudaHostRegisterMapped);
if(result != cudaSuccess) {
printf("Error in cudaHostRegister: %s.\n", cudaGetErrorString(result));
return -1;
}
我正在使用nvcc标志compute_11和sm_11在VisualStudio2010Premium中编译,一切都在我的笔记本电脑上正确工作,它运行的是一个拥有cuda功能版本3.0的Quadro K1000m。
我最近切换到了我的桌面,在那里我尝试使用GeForce 8600 GT和GeForce 9500 GT运行,这两个版本都有一个cuda功能版本1.1。
根据NVIDIA对cudaHostRegister的文档,库达能力为1.1及以上的卡应该允许使用cudaHostRegisterMapped:
cudaHostRegisterMapped:将分配映射到CUDA地址空间。可以通过调用cudaHostGetDevicePointer()获得指向内存的设备指针。此特性仅适用于计算能力大于或等于1.1的GPU。
经过一些搜索,cudaHostRegisterMapped似乎需要对页对齐的内存.我认为这可能是我的3.0卡和1.1卡的不同之处,因此我屏蔽了地址以获得对页地址,并在size字段中使用页的大小(4096字节),如下所示:
unsigned __int64 mem;
unsigned __int64 *pMem = &mem;
unsigned __int64 memAddr = (unsigned __int64)pMem;
cudaError_t result;
pMem = (unsigned __int64 *)(memAddr & 0xFFFFFFFFFFFFF000);
result = cudaHostRegister(pMem, 4096, cudaHostRegisterMapped);
if(result != cudaSuccess) {
printf("Error in cudaHostRegister: %s.\n", cudaGetErrorString(result));
return -1;
}
此代码也适用于我的3.0卡,但失败的结果与我的1.1卡上的结果相同。cudaHostRegister函数返回错误cudaErrorInvalidValue
,指示:
传递给API调用的一个或多个参数不在可接受的值范围内。
我已经找不到更多关于为什么这个函数会像这样失败的原因了。感谢任何人能提供的任何帮助。
基于魔爪响应的编辑,我至少验证了我的一张卡(9500 GT,我没有在8600 GT上运行它)确实支持内存映射,根据NVIDIA随SDK附带的deviceQuery可执行文件。
发布于 2012-09-06 15:26:54
某些计算功能1.1设备支持映射内存,但并非所有这些设备都支持映射内存。集成芯片组的MCP79系列(so离子,和9300 M/9400 M)支持映射内存。旧的计算能力1.1设备,如您的8600 not和9500 not,但是,不支持映射内存。
您可以使用cudaGetDeviceProperties
API调用以编程方式检查这一点;canMapHostMemory
将告诉您给定设备是否支持映射内存。
https://stackoverflow.com/questions/12301772
复制相似问题