3

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作为参数传递给 kernel allocate_p,它将被分配给p(而不是malloc()),那么代码运行良好。

我在做什么错/我们如何malloc()在主机端功能中使用分配的设备内存?

4

1 回答 1

3

据我所知,无法使用主机 API 函数复制运行时堆内存。这在 CUDA 4.x 中肯定是不可能的,而 CUDA 5.0 候选版本并没有改变这一点。我能提供的唯一解决方法是使用内核“收集”最终结果并将它们填充到设备传输缓冲区或零拷贝内存中,这些内存可以通过 API 或直接从主机访问。您可以在此答案另一个问题中看到此方法的示例,来自 NVIDIA 的 Mark Harris 确认这是 CUDA 运行时中(当时)当前实现的限制。

于 2012-09-03T16:02:35.167 回答