【发布时间】:2012-10-03 02:32:04
【问题描述】:
我想在 cuda 内核中执行一些虚拟方法,但我不想在同一个内核中创建对象,而是想在主机上创建它并将其复制到 gpu 内存。
我成功地在内核中创建对象并调用虚拟方法。复制对象时会出现问题。这是有道理的,因为显然虚函数指针是伪造的。 所发生的只是“Cuda 网格启动失败”,至少 Nsight 是这么说的。 但是当查看 SASS 时,它会在取消引用虚函数指针时崩溃,这是有道理的。
我当然在使用 Cuda 4.2 以及在适配卡上使用“compute_30”进行编译。
那么推荐的方法是什么?还是根本不支持此功能?
我的想法是先运行一个不同的内核,它会创建虚拟对象并在复制对象之前提取虚函数指针以“修补”我的对象。遗憾的是,这并没有真正起作用(还没有弄清楚),而且这将是一个丑陋的解决方案。
附:这实际上是this 问题的重播,遗憾的是从未完全回答。
编辑:
所以我找到了一种方法来做我想做的事。但要明确一点:这根本不是答案或解决方案,答案已经提供,这只是一个 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 作为“修补”对象的查找。
但再说一遍:我不会在任何严肃的事情上使用它,因为在性能方面,虚函数根本不是很好。
【问题讨论】:
-
这是一个完全重复的问题,但我投票决定关闭另一个问题,因为对方的提问者自从他提出这个问题后就没有参加过 SO。如果您正在阅读本文并可以投票关闭,请投票关闭the other question。
标签: c++ cuda virtual-functions