2016-02-13 86 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