CUDA / C - 在内核函数中使用malloc会产生奇怪的结果

时间:2017-07-04 08:51:44

标签: cuda malloc gpgpu

我是CUDA / C的新手,也是堆栈溢出的新手。这是我的第一个问题。

我正在尝试在内核函数中动态分配内存,但结果是意外的。 我在内核中使用malloc()读取可以降低性能很多,但我仍然需要它,所以我首先尝试使用简单的int **数组来测试可能性,然后我实际上需要分配更复杂的结构

在我的主要部分中,我使用cudaMalloc()int *数组分配空间,然后我使用malloc()为内核函数中的每个线程为每个索引分配数组外部数组。然后我使用另一个线程来检查结果,但它并不总是有效。

这是主要代码:

#define N_CELLE 1024*2
#define L_CELLE 512

extern "C" {

int main(int argc, char **argv) {
  int *result = (int *)malloc(sizeof(int));
  int *d_result;
  int size_numbers = N_CELLE * sizeof(int *);
  int **d_numbers;

  cudaMalloc((void **)&d_numbers, size_numbers);
  cudaMalloc((void **)&d_result, sizeof(int *));

  kernel_one<<<2, 1024>>>(d_numbers);
  cudaDeviceSynchronize();
  kernel_two<<<1, 1>>>(d_numbers, d_result);

  cudaMemcpy(result, d_result, sizeof(int), cudaMemcpyDeviceToHost);

  printf("%d\n", *result);

  cudaFree(d_numbers);
  cudaFree(d_result);
  free(result);
}

}

我使用了extern "C"因为我在导入标头时无法编译,这在此示例代码中未使用。我贴了它,因为我不知道这是否相关。

这是kernel_one代码:

__global__ void kernel_one(int **d_numbers) {
  int i = threadIdx.x + blockIdx.x * blockDim.x;
  d_numbers[i] = (int *)malloc(L_CELLE*sizeof(int));
  for(int j=0; j<L_CELLE;j++)
    d_numbers[i][j] = 1;
}

这是kernel_two代码:

__global__ void kernel_two(int **d_numbers, int *d_result) {
  int temp = 0;
  for(int i=0; i<N_CELLE; i++) {
    for(int j=0; j<L_CELLE;j++)
      temp += d_numbers[i][j];     
  }
  *d_result = temp;
}

一切正常(也就是计数是正确的),直到我在设备内存中使用少于1024 * 2 * 512的总块。例如,如果我#define N_CELLE 1024*4程序开始提供“随机”结果,例如负数。 知道问题可能是什么? 谢谢任何人!

2 个答案:

答案 0 :(得分:3)

内核内存分配从静态分配的运行时堆中提取内存。在较大的大小,您超过该堆的大小,然后您的两个内核尝试从未初始化的内存中读取和写入。这会在设备上产生运行时错误,并使结果无效。如果您在主机端添加了正确的API错误检查,或者使用cuda-memcheck实用程序运行代码,您就会知道这一点。

解决方案是确保在尝试运行内核之前将堆大小设置为适当的值。添加这样的东西:

 size_t heapsize = sizeof(int) * size_t(N_CELLE) * size_t(2*L_CELLE);
 cudaDeviceSetLimit(cudaLimitMallocHeapSize, heapsize);

在任何其他API调用之前,您的主机代码应解决问题。

答案 1 :(得分:0)

我对CUDA一无所知,但这些都是严重的错误:

  • 您无法从int**转换为void**。它们不兼容。铸造并没有解决问题,但隐藏了它。
  • &d_numbers给出指向的指针的地址,这是错误的。它的类型为int***

上述两个错误都会导致未定义的行为。如果你的程序似乎在某种程度上起作用,那只是纯粹的(坏的)运气。