TL;DRmul.hi.s64
これは、プラットフォーム固有の PTX 命令のエミュレーションにおけるバグのsm_5x
ようです。そのため、NVIDIA にバグ レポートを提出することをお勧めします。
一般に、NVIDIA GPU は 32 ビット アーキテクチャであるため、すべての 64 ビット整数命令にはエミュレーション シーケンスが必要です。sm_2x
およびsm_3x
プラットフォームの 64 ビット整数乗算の特定のケースでは、これらはIMAD.U32
32 ビット整数乗算加算命令であるマシン コード命令から構築されます。
Maxwell アーキテクチャ (つまりsm_5x
) では、高スループットで幅の狭い整数乗加算命令XMAD
が導入されましたが、低スループットの従来の 32 ビット整数乗算IMUL
は明らかに保持されていました。sm_5x
CUDA 7.5 ツールチェーンによって生成された逆アセンブルされたマシン コードを調べるとcuobjdump --dumpsass
、ptxas
最適化レベル-O0
(デバッグ ビルドに使用される) では、64 ビット乗算がIMUL
命令でエミュレートされ、最適化レベル-O1
以上XMAD
では使用されることが示されます。根本的に異なる 2 つのエミュレーション シーケンスが採用されている理由が思いつきません。
結局のところ、 forのベースのIMUL
エミュレーションは壊れていますが、ベースのエミュレーションは正常に動作します。したがって、考えられる回避策の 1 つは、コマンド ラインで指定して、少なくともforの最適化レベルを利用することです。リリース ビルドはデフォルトでを使用するため、リリース ビルドには修正アクションは必要ありません。mul.hi.s64
sm_5x
XMAD
-O1
ptxas
-Xptxas -O1
nvcc
-Xptxas -O3
コード分析から、 のエミュレーションは のエミュレーションmul.hi.s64
のラッパーとして実装されておりmul.hi.u64
、この後者のエミュレーションは を含むすべてのプラットフォームで正常に動作するようですsm_5x
。したがって、別の可能な回避策は、独自のラッパーを使用することmul.hi.u64
です。この場合、インライン PTX を使用したコーディングは不要です。デバイス組み込み関数およびを介してmul.hi.s64
およびmul.hi.u64
にアクセスできるためです。以下のコードからわかるように、結果を符号なし乗算から符号付き乗算に変換するための調整はごく簡単です。__mul64hi()
__umul64hi()
long long int m1, m2, result;
#if 0 // broken on sm_5x at optimization level -O0
asm(" mul.hi.s64 %0, %1, %2; \n\t"
: "=l"(result)
: "l"(m1), "l"(m2));
#else
result = __umul64hi (m1, m2);
if (m1 < 0LL) result -= m2;
if (m2 < 0LL) result -= m1;
#endif