固定内存应该可以提高主机到设备的传输速率(api引用)。但是我发现我不需要调用cuMemcpyHtoD来让内核访问这些值,或者cuMemcpyDtoA让主机读回值。我认为这不会起作用,但确实如此:
__global__ void testPinnedMemory(double * mem)
{
double currentValue = mem[threadIdx.x];
printf("Thread id: %d, memory content: %f\n", threadIdx.x, currentValue);
mem[threadIdx.x] = currentValue+10;
}
void test()
{
const size_t THREADS = 8;
double * pinnedHostPtr;
cudaHostAlloc((void **)&pinnedHostPtr, THREADS, cudaHostAllocDefault);
//set memory values
for (size_t i = 0; i < THREADS; ++i)
pinnedHostPtr[i] = i;
//call kernel
dim3 threadsPerBlock(THREADS);
dim3 numBlocks(1);
testPinnedMemory<<< numBlocks, threadsPerBlock>>>(pinnedHostPtr);
//read output
printf("Data after kernel execution: ");
for (int i = 0; i < THREADS; ++i)
printf("%f ", pinnedHostPtr[i]);
printf("\n");
}
输出:
Data after kernel execution: 10.000000 11.000000 12.000000 13.000000 14.000000 15.000000 16.000000 17.000000
Thread id: 0, memory content: 0.000000
Thread id: 1, memory content: 1.000000
Thread id: 2, memory content: 2.000000
Thread id: 3, memory content: 3.000000
Thread id: 4, memory content: 4.000000
Thread id: 5, memory content: 5.000000
Thread id: 6, memory content: 6.000000
Thread id: 7, memory content: 7.000000
我的问题是:
我正在使用CUDA Toolkit 5.5,Quadro 4000,驱动程序设置为TCC模式,编译选项sm_20,compute_20
答案 0 :(得分:9)
恭喜!您正在使用较新的CUDA版本遇到2.x计算能力+ TCC + 64位操作系统功能:)
阅读其余内容以了解更多信息!
首先是CUDA教给我们的一个小理论总结:
固定内存不是零复制,因为GPU无法访问它(它没有映射到其地址空间中),而是用于有效地从主机传输到GPU。它是页面锁定(有价值的内核资源)内存,与可分页的普通内存相比具有一些性能优势。
固定零拷贝内存是页锁定内存(通常分配有cudaHostAllocMapped
标志),自映射到其地址空间后,GPU也会使用该内存。 / p>
为什么你在没有明确指定的情况下从设备访问从主机分配的内存?
查看CUDA 4.0(及更高版本)的发行说明:
- (Windows和Linux)添加了对统一虚拟地址空间的支持。
现在支持64位且计算2.0及更高版本功能的设备 在主机和所有设备之间共享一个统一的地址空间。 这意味着用于访问主机上的内存的指针是 与用于访问设备内存的指针相同。因此, 可以直接从其指针值查询存储器的位置; 无需指定存储器复制的方向。
总结一下:如果你的卡是2.0+(它是:https://developer.nvidia.com/cuda-gpus),你运行的是64位操作系统,而在Windows上你有一个TCC模式,你自动使用主机和设备之间的UVA (Unified Virtual Addressing) 。这意味着:使用类似零拷贝的访问自动增强代码。
这也在段落“主机分配的主机内存的自动映射”中的CUDA documentation for the current version
答案 1 :(得分:5)
映射内存是一种固定内存。它是在您固定内存并传递cudaHostAllocMapped
标志时创建的。 然而,即使您已指定cudaHostAllocDefault
,在某些情况下内存也会被“映射”。我相信TCC模式与64位操作系统相结合足以满足“自动映射”功能所需的环境。
核心问题是UVA是否有效。在你的情况下,它是。
关于为什么具有显式功能的问题,它适用于UVA无效的情况(例如在32位主机操作系统中)。
来自documentation的(当UVA生效时):
主机分配的主机内存的自动映射
使用cudaMallocHost()通过所有设备分配的所有主机内存 始终可以从所有设备直接访问cudaHostAlloc() 支持统一寻址。无论如何都是这种情况 是否标志cudaHostAllocPortable和cudaHostAllocMapped 是指定的。指针值,通过它分配主机内存 可以在支持统一的所有设备上的内核中访问 寻址与该内存的指针值相同 在主机上访问。没有必要打电话 cudaHostGetDevicePointer()获取这些设备的指针 分配。