CUDA编程指南指出“通过malloc()
分配的内存可以使用运行时复制(即通过调用设备内存中的任何复制内存函数)”,但不知怎的,我无法重现这一点功能。代码:
#include <cstdio>
__device__ int* p;
__global__ void allocate_p() {
p = (int*) malloc(10);
printf("p = %p (seen by GPU)\n", p);
}
int main() {
cudaError_t err;
int* localp = (int*) malloc(10);
allocate_p<<<1,1>>>();
cudaDeviceSynchronize();
//Getting pointer to device-allocated memory
int* tmpp = NULL;
cudaMemcpyFromSymbol(&tmpp, p, 4);
printf("p = %p (seen by CPU)\n", tmpp);
//cudaMalloc((void**)&tmpp, 40);
err = cudaMemcpy(tmpp, localp, 40, cudaMemcpyHostToDevice);
cudaDeviceSynchronize();
printf(" err:%i %s", (int)err, cudaGetErrorString(err));
delete localp;
return 0;
}
输出崩溃:
p = 0x601f920 (seen by GPU)
p = 0x601f920 (seen by CPU)
err:11 invalid argument
我收集说,主持人在设备上看到了合适的地址,但不知道它是不是来自malloc()
。
如果我先由cudaMalloc((void**)&np, 40);
分配,然后将指针np
作为参数传递给内核allocate_p
,那么它将被分配到p
(而不是{{1}然后代码运行正常。
我做错了什么/如何在主机端功能中使用malloc()
分配的设备内存?
答案 0 :(得分:3)
据我所知,无法使用主机API函数复制运行时堆内存。在CUDA 4.x中肯定是不可能的,并且CUDA 5.0发布候选版本没有改变这一点。我可以提供的唯一解决方法是使用内核“收集”最终结果并将它们填充到设备传输缓冲区或零拷贝内存中,可以通过API或直接从主机访问。您可以在this answer和another question中看到此方法的示例,其中来自NVIDIA的Mark Harris确认这是CUDA运行时(当时)当前实现的限制。