如何使用cudaMallocManaged在指针位置初始化对象?(C++)

How to initialize an object at pointer location with cudaMallocManaged? (C++)

本文关键字:对象 C++ 初始化 位置 何使用 cudaMallocManaged 指针      更新时间:2023-10-16

下面显示的是我正在使用的代码的简化版本,当我不使用cudaMallocManaged,只使用new关键字初始化所有内容时,所有内容都运行得很好。我已经将问题缩小到在for循环中初始化数组中元素的方式,但我不知道这里出了什么问题。当打印比较指针时,一切似乎都是应该的,但它会产生分段错误。

#include <iostream>
class B
{
public:
__device__ __host__ virtual void test() = 0;
};
class A: public B
{
public:
__device__ __host__ A(int x) {number = x;};
__device__ __host__ void test() {printf("test called!n");}
int number;
};
int main(int argc, char const *argv[])
{
// Size of array.
static const int count = 2;
// Create array of pointers to A objects in memmory.
B** list; // = new B*[count];
cudaMallocManaged(&list, count*sizeof(B*));
// Create objects for in array.
for (int i = 0; i < count; i++)
{
A* tempPointer;
cudaMallocManaged(&tempPointer, sizeof(A));
*tempPointer = A(500);
list[i] = tempPointer;
}
// Gives a segmentation fault.
for (int i = 0; i < count; i++)
list[i]->test();
// Free memmory.
for (int i = 0; i < count; i++)
cudaFree(list[count]);
cudaFree(list);
}

将其用于循环将导致工作代码,但我确实需要使用cudaMallocManaged,因此这不是一个选项:

for (int i = 0; i < count; i++)
{
A* tempPointer = new A(500);
list[i] = tempPointer;
}

这里的问题是初始化一个包含虚拟方法的类的对象的方法,因此初始化一个虚拟函数指针表:

class B
{
public:
__device__ __host__ virtual void test() = 0;
};
class A: public B
{
public:
__device__ __host__ A(int x) {number = x;};
__device__ __host__ void test() {printf("test called!n");}
int number;
};

不是通过对象复制:

*tempPointer = A(500);

该方法不会初始化对象中的虚拟函数指针表。

相反,对于这种特殊的情况,我的建议是使用新的放置:

$ cat t1674.cu
#include <iostream>
#include <stdio.h>
class B
{
public:
__device__ __host__ virtual void test() = 0;
};
class A: public B
{
public:
__device__ __host__ A(int x) {number = x;};
__device__ __host__ void test() {printf("test called!n");}
int number;
};
int main(int argc, char const *argv[])
{
// Size of array.
static const int count = 2;
// Create array of pointers to A objects in memmory.
B** list; // = new B*[count];
cudaMallocManaged(&list, count*sizeof(B*));
// Create objects for in array.
for (int i = 0; i < count; i++)
{
A* tempPointer;
cudaMallocManaged(&tempPointer, sizeof(A));
//        *tempPointer = A(500);
list[i] = new(tempPointer) A(500);
}
// Gives a segmentation fault.
for (int i = 0; i < count; i++)
list[i]->test();
// Free memmory.
for (int i = 0; i < count; i++)
cudaFree(list[count]);
cudaFree(list);
}
$ nvcc -o t1674 t1674.cu
$ cuda-memcheck ./t1674
========= CUDA-MEMCHECK
test called!
test called!
========= ERROR SUMMARY: 0 errors
$

请注意,在上面的文章中,我还修复了代码中的另一个错误,特别是您多次尝试释放指针list[0],这显然是不正确的。我已将其更改为list[count],我认为这是您的意图。

说了这么多,我怀疑你可能很快就会遇到这种方法的问题。CUDA对具有虚拟函数指针表的对象有限制。特别是,对象必须在要使用的域中创建。如果您只想在主机上使用它,请初始化主机上的对象。如果您只想在设备上使用它,请初始化设备上的对象。在一个域中初始化的对象(具有虚拟函数指针表(无法在另一个域安全使用。