如何使用cudaMallocManaged在指针位置初始化对象?(C++)
How to initialize an object at pointer location with cudaMallocManaged? (C++)
下面显示的是我正在使用的代码的简化版本,当我不使用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对具有虚拟函数指针表的对象有限制。特别是,对象必须在要使用的域中创建。如果您只想在主机上使用它,请初始化主机上的对象。如果您只想在设备上使用它,请初始化设备上的对象。在一个域中初始化的对象(具有虚拟函数指针表(无法在另一个域安全使用。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象