2016-02-13 80 views
0

我想我發現一個問題時,使用有符號整數在CUDA PTX 128位有符號乘法。 這裏是我的示例代碼:Cuda簽名128位乘法錯誤

long long result_lo, result_hi; 
asm(" mul.lo.s64 %0, 0, -1;  \n\t" // 0 * -1 = 0 
    " mul.hi.s64 %1, 0, -1;  \n\t" 
    : "=l"(result_lo), "=l"(result_hi)); 

這將產生的結果result_lo = 0x0, result_hi = 0x0。然而,這產生了結果:result_lo = 0x0, result_hi = 0xFFFFFFFFFFFFFFFF這實際上是值2^127 - (2^126 - 1)如果我沒有弄錯,顯然不是零。

首先,我想確保我的理解是正確的,但更重要的是,有沒有辦法解決這個問題?

更新Debug mod更改爲Release模式修復此問題,仍然想知道這是否是cuda中的錯誤?

更新2 報告這個錯誤給NVIDIA

二手CUDA工具包7.5與Visual Studio 2013年x64 Debugsm_52compute_52

+0

這可能是在調試模式下的一個錯誤的'sm_52'。我可以在'sm_52'調試模式下重現它,但不能在'sm_35'或'sm_20'上重現。請注意,麥克斯韋設備不具有原生64位整數乘法運算;編譯器會產生32位操作數序列。因此[this](http://stackoverflow.com/questions/6162140/128-bit-integer-on-cuda)可能是有趣的。 –

+0

@RobertCrovella由於sm_5x(相對於sm_2x,sm_3x)甚至沒有在硬件中的32位整數乘法器,用於在sm_5x 64位整數乘法仿真序列必然不同於用於sm_2x,sm_3x仿真序列不同。特定於sm_5x的錯誤報告似乎是按順序排列的。 – njuffa

+0

是的,我已經提交了一個bug。 –

回答

3

TL; DR這似乎是在PTX指令mul.hi.s64特定於sm_5x平臺的仿真中的錯誤,所以申請與NVIDIA bug報告是行動的推薦套餐。

通常,NVIDIA GPU是32位體系結構,因此所有64位整數指令都需要仿真序列。在64位整數乘法的情況下,對於sm_2xsm_3x平臺,這些是從機器碼指令IMAD.U32構造的,這是一個32位整數乘加指令。

對於麥克斯韋架構(即,sm_5x),高吞吐量的,但較低的寬度,整數乘法 - 加法指令XMAD引入,雖然低吞吐量的傳統的32位整數multipy IMUL顯然保留。通過CUDA 7.5工具鏈生成sm_5x的拆卸機器代碼(cuobjdump --dumpsass)的檢查顯示,對於ptxas優化級別-O0(用於調試構建),64位乘法是用IMUL指令來模擬的,而對於優化級別-O1和更高使用XMAD。我想不出兩個根本不同的仿真序列被採用的原因。

事實證明,爲mul.hi.s64sm_5xIMUL基於仿真而XMAD基於仿真正常工作被打破。因此,一種可能的解決方法是通過在nvcc命令行上指定-Xptxas -O1來針對ptxas利用至少-O1的優化級別。請注意,發佈版本默認使用-Xptxas -O3,因此發佈版本不需要糾正操作。

從代碼分析,爲mul.hi.s64仿真實現爲圍繞仿真的包裝爲mul.hi.u64,而後者仿真似乎在所有平臺上,包括sm_5x做工精細。因此,另一個可能的解決方法是使用我們自己的包裝mul.hi.u64。帶內嵌PTX編碼是在這種情況下是不必要的,因爲mul.hi.s64mul.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