我花了 2 天时间试图解决这个问题,但一无所获。假设我有一个看起来像这样的结构:
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
。
如有任何信息,我们将不胜感激!
最佳答案
在评论中进行了一些对话之后,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!
$
关于这个问题:
Is it even best practice to do it this way rather than pass a single struct with arrays that are num_of_things large?
是的,这是一个明智的做法,无论是否使用托管内存都是可用的。使用单个 cudaMemcpy
调用(例如,如果托管内存未正在使用。)
要解决有关 cudaMallocManaged
的第三个(flags
)参数的问题:
- 如果指定,则传递零是不正确的(尽管 OP 发布的代码没有提供证据。)您应该使用 the documented choices 之一。 .
- 如果未指定,这仍然有效,并提供默认参数
cudaMemAttachGlobal
。这可以通过查看cuda_runtime.h
文件或简单地编译/运行上面的测试代码来确认。这个特殊点似乎是文档中的一个疏忽,我已经在 NVIDIA 提交了一个内部问题来查看它。因此,将来可能会就此更改文档。
最后,proper cuda error checking每当您在使用 CUDA 代码时遇到问题时,它始终是有序的,并且使用此类代码可能会揭示所犯的任何错误。 OP 在代码注释中报告的 seg 错误几乎可以肯定是由于 cudaMallocManaged
调用失败(可能是因为错误地提供了一个零参数),结果是有问题的指针(things
) 没有实际分配。该指针的后续使用将导致段错误。我的测试代码演示了如何避免段错误,即使 cudaMallocManaged
调用由于某种原因失败,关键是正确的错误检查。
关于c++ - 如何将 C++ 结构数组传递给 CUDA 设备?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34348242/