为什么 CUDA 在访问类成员时崩溃?
Why is CUDA crashing upon accessing member of class?
抱歉,如果这是一个新问题,但我找不到它。我一直在编写一个可以使用CDUA加速的程序。但是,我的方法将严重依赖于将类对象(完全,而不仅仅是它们的成员)传递给内核才能运行。为了确定这是否可行,我编写了一个小型测试程序。
class bulkArray {
public:
double* value;
int xSize;
bulkArray(int xSize) {
value = new double[xSize];
this->xSize = xSize;
}
};
__global__ void addArrays(bulkArray *a, bulkArray *b, bulkArray *c, int N) {
int id = blockIdx.x*blockDim.x + threadIdx.x;
if (id < N)
c->value[id] = a->value[id] + b->value[id];
}
int main() {
int N = 50000000;
bulkArray *a;
bulkArray *b;
bulkArray *c;
a = new bulkArray(N);
b = new bulkArray(N);
c = new bulkArray(N);
// allocate unified memory.
cudaMallocManaged(&a, sizeof(a));
cudaMallocManaged(&b, sizeof(b));
cudaMallocManaged(&c, sizeof(c));
// init vectors on host.
for (int i = 0; i < N; i++) {
// CRASHING HERE.
a->value[i] = sin(i) * cos(i);
b->value[i] = sin(i) * cos(i);
}
int blockSize = 1024;
int gridSize = (int)ceil((float)N / blockSize);
addArrays << <gridSize, blockSize >> > (a, b, c, N);
// sum up vector c.
double sum = 0;
for (int i = 0; i < N; i++) {
sum += c->value[i];
}
cout << "Final result: " << sum << endl;
cudaFree(a);
cudaFree(b);
cudaFree(c);
return 0;
}
不知何故,将 3 个对象加载到统一内存中是有效的,但当我尝试访问它们进行修改时失败。我查看了其他指南和示例,无法完全确定出了什么问题。对于发布的代码量,我深表歉意,但我忍不住担心我正在尝试的内容是不可能的。
您可能对托管内存或cudaMallocManaged
的工作方式有一些误解。 在某些方面,cudaMallocManaged
在概念上类似于C库malloc
,只是它分配了托管内存。 有关在简单的 CUDA 应用程序中使用托管内存的更详细说明,您可能需要参考此博客。
具体来说,下面是代码的一些问题:
对具有嵌入指针的对象数组使用托管分配时,如果要在设备上使用该分配,则需要将所有级别的分配替换为托管分配。 因此,如果要在设备代码中访问该成员/字段,则在构造函数中使用
new
将不起作用。 我们可以在那里替换cudaMallocManaged
。我们不会使用
new
分配指针,然后使用cudaMallocManaged
重新分配相同的指针。在指针上使用 C(或 C++)中的
sizeof
函数时,将返回该指针的大小,而不是它指向的任何内容的大小。 因此,这不是为对象数组分配的明智方法。CUDA 内核启动是异步的,因此在内核启动后,如果要使用托管数据,则需要创建某种同步。
以下是解决上述问题的一组最小修改。 我省略了正确的 CUDA 错误检查,但我强烈建议在开发 CUDA 代码时这样做。 此外,如果您遇到困难,我建议您使用cuda-memcheck
运行此代码:
$ cat t51.cu
#include <iostream>
using namespace std;
class bulkArray {
public:
double* value;
int xSize;
void init(int xSize) {
cudaMallocManaged(&value, xSize*sizeof(double));
this->xSize = xSize;
}
};
__global__ void addArrays(bulkArray *a, bulkArray *b, bulkArray *c, int N) {
int id = blockIdx.x*blockDim.x + threadIdx.x;
if (id < N)
c->value[id] = a->value[id] + b->value[id];
}
int main() {
int N = 50000;
bulkArray *a;
bulkArray *b;
bulkArray *c;
// allocate unified memory.
cudaMallocManaged(&a, sizeof(bulkArray));
cudaMallocManaged(&b, sizeof(bulkArray));
cudaMallocManaged(&c, sizeof(bulkArray));
a->init(N);
b->init(N);
c->init(N);
// init vectors on host.
for (int i = 0; i < N; i++) {
a->value[i] = sin(i) * cos(i);
b->value[i] = sin(i) * cos(i);
}
int blockSize = 1024;
int gridSize = (int)ceil((float)N / blockSize);
addArrays << <gridSize, blockSize >> > (a, b, c, N);
cudaDeviceSynchronize();
// sum up vector c.
double sum = 0;
double sum2 = 0;
for (int i = 0; i < N; i++) {
sum += c->value[i];
sum2 += a->value[i] + b->value[i];
}
cout << "Final result: " << sum << " should be: " << sum2 << endl;
cudaFree(a);
cudaFree(b);
cudaFree(c);
return 0;
}
$ nvcc -arch=sm_35 -o t51 t51.cu
$ cuda-memcheck ./t51
========= CUDA-MEMCHECK
Final result: 0.624013 should be: 0.624013
========= ERROR SUMMARY: 0 errors
$
- 将方法转换为调用该方法的成员函子对象会导致崩溃
- 当从成员类调用封装的std::begin时,程序崩溃
- 如果类的成员,C++数组会导致崩溃
- 调用 lambda 的结构/类成员时程序崩溃并"bad_function_call"
- size_t结构非数组成员崩溃的强制转换
- 为什么 CUDA 在访问类成员时崩溃?
- BOOST :: ASIO使用成员受体而不是新成员时崩溃
- 为什么在复制构造函数中分配联合成员会崩溃
- 调用从 lambda 作为模板参数传递的成员函数指针会崩溃
- 在构造函数因未初始化成员而崩溃之前调用的C++函数
- 清理所拥有的(!)字符串成员时,析构函数偶尔崩溃
- CPPrestsdk 处理程序类在使用 STL 容器作为成员时崩溃
- 崩溃,如果使用向量删除了一个嵌入式容器的destructor中删除char*成员
- MFC对话框成员变量的随机崩溃不在范围中
- OpenCV-将变量添加到类成员崩溃程序
- Visual Studio 2013 因非静态数据成员初始化而崩溃
- 为什么当我删除 std::vector 的成员时我的程序崩溃
- 静态模板成员崩溃
- 调用指向windows过程中C函数的函数的成员指针会导致应用程序崩溃
- 使用成员编写移动构造函数的正确方法unique_ptr(崩溃)