我想在 cuda 内核中执行一些虚拟方法,但是我不想在同一个内核中创建对象,而是想在主机上创建它并将其复制到 gpu 内存。
我成功地在内核中创建对象并调用虚拟方法。复制对象时会出现问题。这是有道理的,因为显然虚函数指针是伪造的。所发生的只是“Cuda 网格启动失败”,至少 Nsight 是这么说的。但是当查看 SASS 时,它会在取消引用虚函数指针时崩溃,这是有道理的。
我当然使用 Cuda 4.2 以及在适配卡上使用“compute_30”进行编译。
那么推荐的方法是什么?还是根本不支持此功能?
我的想法是首先运行一个不同的内核,它创建虚拟对象并在复制它们之前提取虚拟函数指针以“修补”我的对象。可悲的是,这并没有真正起作用(还没有弄清楚),而且这将是一个丑陋的解决方案。
PS这实际上是这个问题的重播,遗憾的是从未完全回答过。
编辑 :
所以我找到了一种方法来做我想做的事。但要明确一点:这根本不是答案或解决方案,答案已经提供,这只是一个 hack,只是为了好玩。
所以首先让我们看看 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 作为“修补”对象的查找。
但是再说一遍:我不会在任何严肃的事情上使用它,因为在性能方面,虚函数根本不是很好。