1

您好,我正在研究另一个任意精度整数库。我想实现乘法,但是当我没有工作时我被卡住_m_pmulhw了。关于 MMX 指令的文档<mmintrin.h>很少。当我测试它时,当我将两个 UINT64_MAX 相乘时,它只会让我胡言乱语。

uint_fast64_t mulH(const uint_fast64_t &a, const uint_fast64_t &b)  {  
    return (uint_fast64_t)_m_pmulhw((__m64)a,(__m64)b);
}
uint_fast64_t mulL(const uint_fast64_t &a, const uint_fast64_t &b)  {  
    return (uint_fast64_t)_m_pmullw((__m64)a,(__m64)b);
}
int main() {
    uint64_t a = UINT64_MAX;
    uint64_t b = UINT64_MAX;
    std::cout <<  std::bitset<64>(mulH(a,b)) << std::bitset<64>(mulL(a,b));
}

output: 00000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000100000000000000010000000000000001 

我不知道为什么它不工作我有一个 A6-4400M APU...

核心信息的输出:MMX * Supports MMX instruction set

所以我想我可以说,它不是不受支持的。如果有人可以给我一些关于如何完成这项工作的提示,谢谢。

编译器:gcc

IDE:视觉工作室代码

4

2 回答 2

3

我想你误解了什么_m_pmulhw。它实际上非常清楚地记录在英特尔的内部指南中:https ://software.intel.com/sites/landingpage/IntrinsicsGuide/#text=_m_pmulhw&expand=4340 。相应的指令是pmulhw,它也清楚地记录在例如 Felix Cloutier 的 x86 指令指南中:https ://www.felixcloutier.com/x86/pmulhw

它将压缩在两个操作数内的四对 16 位整数相乘,然后产生所有四个乘法的高半部分(压缩乘高 - 字)。这意味着,对于输入 0x12345678abcdef01、0x9876543210fedcba,它将乘以、、、,并将每个结果的高 16 位打包到输出中。0x1234 * 0x98760x5678 * 0x54320xabcd * 0x10fe0xef01 * 0xdcba

对于您的示例,您乘以0xffff * 0xffff四次,产生 32 位结果0x00000001-1 * -1,因为这是一个有符号的 16 位乘法),因此进入0x0000000000000000高半部分和0x0001000100010001低半部分 - 这正是您在bitset输出。


如果您正在寻找 128 位乘法,那么实际上并没有它的内在特性(除了_mulx_u64,但它使用了mulx不那么普遍的新指令)。Microsoft 具有非标准_mul128内在函数,但在其他平台上,您可以只使用__int128类型(或本地等效项)来获得 64x64=>128 位乘法。

另外,我强烈建议使用 SSE 指令集而不是旧的 MMX 集;在大多数情况下,SSE 指令更快,使您能够对更广泛的矢量类型进行操作(现在 256 位是标准的,现在可以使用 AVX512),这可以显着提高速度。

于 2020-02-19T04:32:43.223 回答
2

我不是这方面的专家,但根据https://www.felixcloutier.com/x86/pmulhw,这些说明不会进行 64x64->128 乘法;他们做了四个 16x16->32 的乘法。请注意描述中的“包装”一词。此外,它是一个有符号的乘法。

因此,您的 64 位UINT64_MAX值被解释为 的四个字0xffff,也就是说-1。所以你乘以-1,-1四倍。当然,每一个的数字答案都是1。指令的结果pmulhw是结果的高半部分(即 的四个字0x0000),pmullw是结果的低半部分(即 的四个字0x0001)。

这正是你得到的,所以在我看来,这些说明工作得很好。

如果您想对两个 64 位整数进行无符号乘法,那么简单的老式mul指令将满足您的目的,gcc生成它的最简单方法可能是将输入转换__uint128_t为常用运算符并与之相乘*

于 2020-02-19T04:29:36.180 回答