Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CUDA/C-在内核函数中使用malloc会产生奇怪的结果_Cuda_Malloc_Gpgpu - Fatal编程技术网

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

CUDA/C-在内核函数中使用malloc会产生奇怪的结果,cuda,malloc,gpgpu,Cuda,Malloc,Gpgpu,我是CUDA/C新手,也是堆栈溢出新手。这是我的第一个问题 我试图在内核函数中动态分配内存,但结果出乎意料。 我了解到在内核中使用malloc()会大大降低性能,但我还是需要它,所以我首先尝试使用一个简单的int**数组来测试这种可能性,然后我实际上需要分配更复杂的结构 我主要使用cudamaloc()为int*的数组分配空间,然后对内核函数中的每个线程使用malloc()为外部数组的每个索引分配数组。然后我使用另一个线程来检查结果,但它并不总是有效 以下是主要代码: #define N_CEL

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

我试图在内核函数中动态分配内存,但结果出乎意料。 我了解到在内核中使用malloc()会大大降低性能,但我还是需要它,所以我首先尝试使用一个简单的
int**
数组来测试这种可能性,然后我实际上需要分配更复杂的结构

我主要使用
cudamaloc()
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);
}

}
这是两个核心代码:

__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;
}
\uuuu全局\uuuuu无效内核\uu二(int**d\u数字,int*d\u结果){
内部温度=0;

对于(int i=0;i我对CUDA一无所知,但这些是严重的错误:

  • 无法从
    int**
    转换为
    void**
    。它们是不兼容的类型。强制转换不能解决问题,但会隐藏问题
  • &d\u numbers
    给出指向错误指针的指针的地址。该指针的类型为
    int***

以上两个错误都会导致未定义的行为。如果您的程序在某种情况下似乎可以正常工作,那纯粹是(坏的)运气好。

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

解决方案是确保在尝试运行内核之前将堆大小设置为适当的大小。添加如下内容:

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

在任何其他API调用之前,对你的主机代码,应该解决这个问题。

你开始学习C,你的第一个测试项目是…CUDA!好的选择!顺便说一下,你在C++中编码,因为<代码>外部代码“C”/代码>不存在…在C.中,这可以解释你的bug。(d_numbers;
我确信这不会编译。
N_CELLE
如何与内核共享?…N_CELLE的定义与主函数和内核函数的.cu文件相同。我修复了粘贴错误,thx。我可能错了,但这就是我看到的cudamaloc的用法API@Ratacand我非常怀疑它是否告诉您将
int***
传递给函数需要一个
void**
。那么你建议怎么做?当然你可以将
int**
转换为
void**
。C11 6.3.2.3第7点说,指向一个对象类型的指针可能会转换为指向另一个对象类型的指针,并且只有当结果指针未对齐时,操作才是未定义的。我认为我们可以安全地假设
void*
与任何sane平台上的
int*
具有相同的对齐要求。@rata首先要摆脱
&
?Thx@talonmes我做了一次快速尝试,效果很好!我明天会做其他测试。我尝试了
cuda memcheck
,但它给出了
内部错误(7)-在我运行的每个程序上都没有找到CUDA-MEMCHECK结果,我无法找到解决方案
 size_t heapsize = sizeof(int) * size_t(N_CELLE) * size_t(2*L_CELLE);
 cudaDeviceSetLimit(cudaLimitMallocHeapSize, heapsize);