【问题标题】:Is it possible to use SSE and SSE2 to make a 128-bit wide integer?是否可以使用 SSE 和 SSE2 制作 128 位宽的整数?
【发布时间】:2012-08-25 09:46:08
【问题描述】:

我希望进一步了解 SSE2 的功能,并想知道是否可以制作一个支持加法、减法、XOR 和乘法的 128 位宽整数?

【问题讨论】:

  • 唯一的 128 位操作是 OR、XOR 和移位。加法和减法最高为 64 位,较新的乘法最多允许 32 位。为了实现 128 位加法,您需要手动处理进位标志,并首先失去所有性能优势。
  • @BitBank:有 AND,也有 ANDNOT,但你的观点仍然有效 - SSE2 中没有 128 位 算术 运算。
  • 从技术上讲,您可以。但是没有非按位指令可以这样做。所以你必须模仿一切——在这一点上,它不会比在 x64 上使用进位标志更好......
  • 非常感谢您的回答(嗯,cmets!),很遗憾,我一度以为我们已经掌握了 128 位处理器。但是,任何更高版本的 SSE 是否有 128 位的这些功能?

标签: assembly sse sse2


【解决方案1】:

SIMD 旨在同时处理多个小值,因此不会有任何结转到更高的单元,您必须手动执行此操作。在 SSE2 中没有进位标志,但您可以轻松地将进位计算为 carry = sum < acarry = sum < b,如 this。更糟糕的是,SSE2 也没有 64 位比较,因此您必须使用一些解决方法,例如 here

这是基于上述思想的未经测试、未经优化的 C 代码:

inline bool lessthan(__m128i a, __m128i b){
    a = _mm_xor_si128(a, _mm_set1_epi32(0x80000000));
    b = _mm_xor_si128(b, _mm_set1_epi32(0x80000000));
    __m128i t = _mm_cmplt_epi32(a, b);
    __m128i u = _mm_cmpgt_epi32(a, b);
    __m128i z = _mm_or_si128(t, _mm_shuffle_epi32(t, 177));
    z = _mm_andnot_si128(_mm_shuffle_epi32(u, 245),z);
    return _mm_cvtsi128_si32(z) & 1;
}

inline __m128i addi128(__m128i a, __m128i b)
{
    __m128i sum = _mm_add_epi64(a, b);
    __m128i mask = _mm_set1_epi64(0x8000000000000000);    
    if (lessthan(_mm_xor_si128(mask, sum), _mm_xor_si128(mask, a)))
    {
        __m128i ONE = _mm_setr_epi64(0, 1);
        sum = _mm_add_epi64(sum, ONE);
    }

    return sum;
}

如您所见,代码需要更多指令,即使经过优化,它仍可能比 x86_64 中的简单 2 ADD/ADC 对(或 x86 中的 4 条指令)长得多


如果您有多个 128 位整数要并行添加,SSE2 会有所帮助。但是,您需要正确排列值的高位和低位部分,以便我们可以一次添加所有低位部分,一次添加所有高位部分

另见

【讨论】:

  • 你可以用 SSE4.1 做 64 位相等比较,但我仍然认为它不会比简单的标量代码更快
  • 我认为您的意思是来自 SSE4.2 而不是 SSE4.1 的 PCMPGTQ(比较压缩的有符号 64 位数据)。
猜你喜欢
  • 2012-03-10
  • 2014-07-09
  • 2013-09-23
  • 2012-11-08
  • 2012-07-19
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多