cuda カーネルでいくつかの仮想メソッドを実行したいのですが、同じカーネルでオブジェクトを作成する代わりに、ホストで作成して gpu メモリにコピーしたいと考えています。
カーネルでオブジェクトを正常に作成し、仮想メソッドを呼び出しています。オブジェクトをコピーするときに問題が発生します。明らかに仮想関数ポインターが偽物であるため、これは理にかなっています。何が起こるかは、単に「Cuda グリッドの起動に失敗しました」です。少なくともこれは Nsight の言うことです。しかし、SASS を見ると、仮想関数ポインターの逆参照でクラッシュします。これは理にかなっています。
もちろん、私は Cuda 4.2 を使用しており、適切なカードで「compute_30」を使用してコンパイルしています。
では、おすすめの行き方は?それとも、この機能は単にサポートされていないのでしょうか?
最初に別のカーネルを実行してダミーオブジェクトを作成し、仮想関数ポインターを抽出してオブジェクトをコピーする前に「パッチ」するという考えがありました。悲しいことに、これは実際には機能していません (まだ理解していません)。
PS これは実際にはこの質問の再実行であり、残念ながら完全には回答されていません。
編集 :
だから私は自分がやりたいことをする方法を見つけました。しかし、明確にするために:これはまったく答えや解決策ではありません。答えはすでに提供されています。これは単なる楽しみのためのハックです。
まず、仮想メソッドを呼び出すときに 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 をオブジェクトのルックアップとして使用して「パッチを当てる」ことができます。
しかし、繰り返しになりますが、パフォーマンスに関しては、仮想関数はまったく優れていないため、これを深刻なものには使用しません。