Cuda签署了128位乘法错误

时间:2016-02-13 22:53:41

标签: cuda ptx

我认为在使用有符号整数在cuda PTX中进行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报告了这个错误

在Visual Studio 2013中使用过Cuda toolkit 7.5。x64 Debugsm_52compute_52

1 个答案:

答案 0 :(得分:3)

TL; DR 这似乎是模拟mul.hi.s64平台专用的PTX指令sm_5x的错误,因此向NVIDIA提交错误报告是推荐的行动方案。

通常,NVIDIA GPU是32位架构,因此所有64位整数指令都需要仿真序列。在64位整数乘法的特定情况下,对于sm_2xsm_3x平台,这些是从机器代码指令IMAD.U32构造的,这是一个32位整数乘加指令。

对于Maxwell架构(即sm_5x),引入了高吞吐量但宽度较低的整数乘加指令XMAD,尽管是低吞吐量的传统32位显然保留了整数乘法IMUL。通过带有sm_5x的CUDA 7.5工具链检查为cuobjdump --dumpsass生成的反汇编机器代码,显示ptxas优化级-O0(用于调试版本),64-使用IMUL指令模拟位乘法,而使用更高级-O1和更高XMAD。我想不出为什么采用两种根本不同的仿真序列的原因。

事实证明,基于IMUL的基于mul.hi.s64的{​​{1}}基于sm_5x的模拟已经被打破,而基于XMAD的模拟工作正常。因此,一种可能的解决方法是通过在-O1命令行上指定ptxas,为-Xptxas -O1使用至少nvcc的优化级别。请注意,发布版本默认使用-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