如何将结构的C ++数组传递给CUDA设备?

时间:2015-12-18 03:46:29

标签: c++ pointers image-processing cuda parallel-processing

我花了两天的时间试图解决这个问题并且无处可去。假设我有一个看起来像这样的结构:

struct Thing {
    bool is_solid;
    double matrix[9];
}

我想创建一个名为things的结构数组,然后在GPU上处理该数组。类似的东西:

Thing *things;
int num_of_things = 100;
cudaMallocManaged((void **)&things, num_of_things * sizeof(Thing));

// Something missing here? Malloc individual structs? Everything I try doesn't work.

things[10].is_solid = true; // Segfaults

这样做是否是最好的做法,而不是使用num_of_things大的数组传递单个结构?在我看来,如果你已经拥有数组(例如matrix,那就需要9 * num_of_things)会变得非常讨厌。

任何信息都将非常感谢!

1 个答案:

答案 0 :(得分:3)

在评论中的一些对话框之后,似乎OP发布的代码没有问题。我能够成功编译并运行围绕该代码构建的测试用例,OP也是如此:

$ cat t1005.cu
#include <iostream>

struct Thing {
    bool is_solid;
    double matrix[9];
};

int main(){

  Thing *things;
  int num_of_things = 100;
  cudaError_t ret = cudaMallocManaged((void **)&things, num_of_things * sizeof(Thing));
  if (ret != cudaSuccess) {
    std::cout << cudaGetErrorString(ret) << std::endl;
    return 1;}
  else {
    things[10].is_solid = true;
    std::cout << "Success!" << std::endl;
    return 0;}
}
$ nvcc -arch=sm_30 -o t1005 t1005.cu
$ ./t1005
Success!
$

关于这个问题:

  

这样做是否是最好的做法,而不是使用num_of_things大的数组传递单个结构?

是的,这是一种明智的做法,无论是否使用托管内存,都可以使用。可以使用单个cudaMemcpy调用以简单的方式将一个或多或少任何不包含动态分配数据的嵌入指针的结构数组传输到GPU(例如,如果未使用托管内存)。 )

要解决有关flags的第3个{cudaMallocManaged)参数的问题:

  1. 如果指定了,则传递零是不正确的(尽管OP发布的代码没有提供任何证据。)您应该使用the documented choices之一。
  2. 如果未指定,则仍然有效,并提供默认参数cudaMemAttachGlobal。这可以通过查看cuda_runtime.h文件或者仅编译/运行上面的测试代码来确认。这个特殊点似乎是对文档的疏忽,我在NVIDIA上提出了一个内部问题来看一看。因此,文件可能会在未来发生变化。
  3. 最后,只要您遇到CUDA代码时遇到问题,proper cuda error checking总是处于正常状态,并且使用这些代码可能会对所发生的任何错误有所了解。 OP在代码注释中报告的seg错误几乎肯定是由于cudaMallocManaged调用失败(可能是因为错误地提供了零参数),因此有问题的指针(things)没有实际分配。随后使用该指针将导致seg错误。我的测试代码演示了如何避免seg错误,即使cudaMallocManaged调用由于某种原因失败,并且关键是正确的错误检查。