x86 - 2 个 64 位整数的 SSE 乘法

标签 x86 sse simd multiplication sse2

如何将两个 64 位整数乘以另外 2 个 64 位整数?
我没有找到任何可以做到这一点的说明。

最佳答案

迟到的答案,但这是巴拉巴斯发布的更好版本。

如果您曾经使用过 GCC 或 Clang 的向量扩展,这就是他们使用的例程。

这使用与长乘法和网格乘法相同的方法。

    65
  * 73
  ----
    15 //   (5 * 3)
   180 //   (6 * 3) * 10
   350 //   (5 * 7) * 10
+ 4200 // + (6 * 7) * 100
------
  4745

然而,它不是以 10 为单位,而是以 32 位为单位,并省略最后一个乘法,因为它总是会移过第 64 位,就像如果你不乘 6*7 一样截断大于 99 的值。
#include <emmintrin.h>

/*
 * Grid/long multiply two 64-bit SSE lanes.
 * Works for both signed and unsigned.
 *   ----------------.--------------.----------------.
 *  |                |   b >> 32    | a & 0xFFFFFFFF |
 *  |----------------|--------------|----------------|  
 *  | d >> 32        |   b*d << 64  |    a*d << 32   |
 *  |----------------|--------------|----------------|
 *  | c & 0xFFFFFFFF |   b*c << 32  |       a*c      |
 *  '----------------'--------------'----------------'
 *  Add all of them together to get the product.
 *
 *  Because we truncate the value to 64 bits, b*d << 64 will be zero,
 *  so we can leave it out.
 *
 *  We also can add a*d and b*c first and then shift because of the
 *  distributive property: (a << 32) + (b << 32) == (a + b) << 32.
 */

__m128i Multiply64Bit(__m128i ab, __m128i cd)
{
    /* ac = (ab & 0xFFFFFFFF) * (cd & 0xFFFFFFFF); */
    __m128i ac = _mm_mul_epu32(ab, cd);

    /* b = ab >> 32; */
    __m128i b = _mm_srli_epi64(ab, 32);

    /* bc = b * (cd & 0xFFFFFFFF); */
    __m128i bc = _mm_mul_epu32(b, cd);

    /* d = cd >> 32; */
    __m128i d = _mm_srli_epi64(cd, 32);

    /* ad = (ab & 0xFFFFFFFF) * d; */
    __m128i ad = _mm_mul_epu32(ab, d);

    /* high = bc + ad; */
    __m128i high = _mm_add_epi64(bc, ad);

    /* high <<= 32; */
    high = _mm_slli_epi64(high, 32);

    /* return ac + high; */
    return _mm_add_epi64(high, ac);
}

Compiler Explorer注意:下面还包含 GCC 矢量扩展版本以供比较。

关于x86 - 2 个 64 位整数的 SSE 乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17863411/

相关文章:

assembly - 组装远调用或远跳转(j* 指令)

assembly - DOS.GetSystemTime 函数 2Ch 不准确

c - 用SSE计算4d vector 平均值

c++ - SSE 内在函数中的 if/else 语句

C simd _m128 晶圆厂

assembly - 如何精确取大型 float 组的平均值?

performance - vgetmantps 与 andpd 获取 float 尾数的说明

c - 如何使用 SSE 进行 uint32/float 转换?

c++ - 如何拦截64位进程中的API方法调用?

c++ - 如何加快积分图像的计算?