首先要分配ZeroCopy内存,你必须指定cudaHostAllocMapped
标志作为参数cudaHostAlloc
.
cudaHostAlloc((void **)&pinnedHostPtr, THREADS * sizeof(double), cudaHostAllocMapped);
依然是pinnedHostPointer
仅用于从主机端访问映射内存。要从设备访问相同的内存,您必须像这样获取指向内存的设备端指针:
double* dPtr;
cudaHostGetDevicePointer(&dPtr, pinnedHostPtr, 0);
将此指针作为内核参数传递。
testPinnedMemory<<< numBlocks, threadsPerBlock>>>(dPtr);
此外,您必须将内核执行与主机同步才能读取更新的值。只需添加cudaDeviceSynchronize
在内核调用之后。
链接问题中的代码正在运行,因为提出问题的人正在 64 位操作系统上运行代码,并且 GPU 具有计算能力 2.0 并启用了 TCC。此配置自动启用统一虚拟寻址GPU 的功能,其中设备将主机 + 设备内存视为单个大内存,而不是单独的内存,并且使用分配的主机指针cudaHostAlloc
可以直接传递给内核。
对于您的情况,最终代码将如下所示:
#include <cstdio>
__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;
}
int main()
{
const size_t THREADS = 8;
double * pinnedHostPtr;
cudaHostAlloc((void **)&pinnedHostPtr, THREADS * sizeof(double), cudaHostAllocMapped);
//set memory values
for (size_t i = 0; i < THREADS; ++i)
pinnedHostPtr[i] = i;
double* dPtr;
cudaHostGetDevicePointer(&dPtr, pinnedHostPtr, 0);
//call kernel
dim3 threadsPerBlock(THREADS);
dim3 numBlocks(1);
testPinnedMemory<<< numBlocks, threadsPerBlock>>>(dPtr);
cudaDeviceSynchronize();
//read output
printf("Data after kernel execution: ");
for (int i = 0; i < THREADS; ++i)
printf("%f ", pinnedHostPtr[i]);
printf("\n");
return 0;
}