私は多くのモジュラー計算を行うことになっているGPUアルゴリズムに取り組んでいます。特に、有限体の行列に対するさまざまな演算は、長期的には次のようなプリミティブ演算になります。(a * b --c * d)mod mまたは(a * b + c)mod mここで、a、b、c、およびdはmを法とする剰余であり、mは32ビットの素数です。
実験を通じて、ハードウェアのGPUでは整数モジュロ(%)および除算演算がサポートされていないため、アルゴリズムのパフォーマンスは低速のモジュラー演算によってほとんど制限されることがわかりました。
誰かがCUDAで効率的なモジュラー計算を実現する方法を教えてくれたらありがたいですか?
これがCUDAにどのように実装されているかを確認するために、次のコードスニペットを使用します。
__global__ void mod_kernel(unsigned *gout, const unsigned *gin) {
unsigned tid = threadIdx.x;
unsigned a = gin[tid], b = gin[tid * 2], m = gin[tid * 3];
typedef unsigned long long u64;
__syncthreads();
unsigned r = (unsigned)(((u64)a * (u64)b) % m);
__syncthreads();
gout[tid] = r;
}
このコードは機能しないはずです。モジュール式の削減がCUDAにどのように実装されているかを確認したかっただけです。
これをcuobjdump--dump-sassで分解すると(アドバイスをくれたnjuffaに感謝します!)、次のように表示されます。
/*0098*/ /*0xffffdc0450ee0000*/ BAR.RED.POPC RZ, RZ;
/*00a0*/ /*0x1c315c4350000000*/ IMUL.U32.U32.HI R5, R3, R7;
/*00a8*/ /*0x1c311c0350000000*/ IMUL.U32.U32 R4, R3, R7;
/*00b0*/ /*0xfc01dde428000000*/ MOV R7, RZ;
/*00b8*/ /*0xe001000750000000*/ CAL 0xf8;
/*00c0*/ /*0x00000007d0000000*/ BPT.DRAIN 0x0;
/*00c8*/ /*0xffffdc0450ee0000*/ BAR.RED.POPC RZ, RZ;
bar.red.popcへの2つの呼び出しの間に、いくつかの高度なアルゴリズム(約50命令以上)を実装する0xf8プロシージャへの呼び出しがあることに注意してください。mod(%)演算が遅いことを驚くことではありません