Cuda虚拟课堂



我想在cuda内核中执行一些虚拟方法,但我不想在同一内核中创建对象,而是想在主机上创建它并将其复制到gpu内存中。

我成功地在内核中创建了对象,并调用了一个虚拟方法。复制对象时出现问题。这是有道理的,因为虚拟函数指针显然是伪造的。所发生的只是"Cuda电网启动失败",至少Nsight是这么说的。但当查看SASS时,它会在取消引用虚拟函数指针时崩溃,这是有道理的。

当然,我使用的是Cuda 4.2,以及在适配卡上使用"compute_30"进行编译。

那么,推荐的方法是什么呢?还是根本不支持此功能?

我有一个想法,首先运行一个不同的内核,它创建虚拟对象,并在复制对象之前提取虚拟函数指针来"修补"我的对象。遗憾的是,这并没有真正奏效(还没有弄清楚),因为这将是一个丑陋的解决方案。

第页。这实际上是这个问题的重演,令人遗憾的是,这个问题从未得到完全回答。

编辑:

所以我找到了一种做我想做的事的方法。但需要明确的是:这根本不是一个答案或解决方案,答案已经提供了,这只是一个破解,只是为了好玩。

因此,首先让我们看看Cuda在调用虚拟方法时在做什么,下面是调试SASS

//R0 is the address of our object
LD.CG R0, [R0];  
IADD R0, R0, 0x4;  
NOP;  
MOV R0, R0;  
LD.CG R0, [R0];
...
IADD R0, RZ, R9;  
MOV R0, R0;  
LDC R0, c[0x2][R0];
...
BRX R0 - 0x5478

因此,假设"c[0x2][INDEX]"对所有内核都是常量,我们只需运行一个内核就可以获得一个类的索引,其中obj是该类的一个新创建的对象:

unsigned int index = *(unsigned int*)(*(unsigned int*)obj + 4);

然后使用这样的东西:

struct entry
{
unsigned int vfptr;// := &vfref, thats our value to store in an object
int dummy;// := 1234, great for debugging
unsigned int vfref;// := &dummy
unsigned int index;
char ClassName[256];//use it as a key for a dict
};

将其存储在主机和设备内存中(内存位置为设备位置),在主机上,您可以使用ClassName查找要"修补"的对象。

但再次强调:我不会在任何严肃的事情中使用它,因为就性能而言,虚拟功能一点也不好。

CUDA编译器和运行时(自CUDA 5.0起)目前不支持您尝试执行的操作。CUDA C编程指南v5.0第D.2.6.3节内容如下:

D.2.6.3虚拟功能

当派生类中的函数重写基类中的虚拟函数时,重写和重写函数上的执行空间限定符(即__host____device__)必须匹配。

不允许将类的对象作为参数传递给__global__函数具有虚拟功能。

编译器将虚拟函数表放在全局内存或常量内存中。

我建议您将类的数据与类的功能分开封装。例如,将数据存储在结构中。如果您计划对这些对象的数组进行操作,请将数据存储在数组结构中(出于性能考虑——不在本问题的范围内)。使用cudaMalloc在主机上分配数据结构,然后将数据作为参数传递给内核,而不是使用虚拟方法传递类。

然后在设备上使用虚拟方法构造对象。具有虚拟方法的类的构造函数会将设备指针内核参数作为参数。然后,虚拟设备方法可以对设备数据进行操作。

同样的方法可以在设备上的一个内核中分配数据,并在设备上另一个内核访问数据(因为同样,具有虚拟函数的类不能作为内核的参数)。

最新更新