【问题标题】:SSE Sum of multiplication of 4 32-bit integersSSE 4 个 32 位整数的乘法之和
【发布时间】:2015-07-29 02:34:22
【问题描述】:

感谢this post 我发现了如何将 4 个 32 位整数相乘。

我现在要做的是总结结果。如何使用内在函数做到这一点?我可以访问 SSE、SSE2 和 AVX。我最初的想法是将res 卸载到一个 int 数组中并对第一个和第三个元素求和,但我想知道是否有更好的方法。

这就是我的代码的样子

__m128i tmp1 = _mm_mul_epu32(a,b); /* mul 2,0*/
__m128i tmp2 = _mm_mul_epu32( _mm_srli_si128(a,4), _mm_srli_si128(b,4)); /* mul 3,1 */
__m128i res = _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0)));

【问题讨论】:

  • 关于乘法,既然你有AVX,你只需要__m128i res = _mm_mullo_epi32(a, b)
  • 您能否说明您受限于哪些 CPU 系列? SSE、SS2 和 AVX 似乎只是一个不太可能的组合 - 你确定你没有 SSE3、SSSE3、SSE4 等吗?
  • SSE 是无意义的,因为它不支持整数 SIMD 操作。
  • 严格来说 SSE 确实 有整数 SIMD 指令,但仅适用于 64 位向量,而不是 128 位。 “SSE”也可以是所有各种 SSE* 指令集的统称,所以我认为我们可以在这里允许它。 ;-)

标签: c sse simd avx sse2


【解决方案1】:

如果你只想要一个水平相加,即将结果向量中的所有 4 个 32 位 int 元素相加,那么你可以移位和相加两次,然后提取一个元素,例如:

__m128i vsum = _mm_add_epi32(v, _mm_srli_si128(v, 8));
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4));
int32_t sum = _mm_cvtsi128_si32(vsum);

【讨论】:

  • 您可以使用_mm_hadd_epi32 两次,但任何一种方法都会绕过溢出。要处理溢出,您需要签署更复杂的扩展。
  • 是的,但_mm_hadd_epi32 是 SSSE3 并且 OP 声称他们只有 SSE、SSE2 和 AVX(诚然,这似乎是一个不太可能的组合,但谁知道 - 也许是没有 SSSE3 的 AMD CPU?)另请注意,如果 OP 有完整的 SSE 指令可用,他们可能会使用_mm_mullo_epi32 而不是上述 SSE2 乘法方法?
  • 哦,我对他的问题的解读不同。我虽然他有 AVX 和下面的一切都不是每个的解决方案。 SSE 无论如何都不支持整数运算。
  • 您可能是对的 - 例如,他显然没有 SSE4,因为他忽略了链接答案中的 SSE4 实现并使用了 SSE2 版本。我对 AMD CPU 不太熟悉,但我知道其中一些缺少 SSSE3 和 SSE4,所以这是我最好的猜测(尽管我不知道是否有任何 AMD CPU 支持 AVX?)。无论如何,我已经要求 OP 进行澄清(见上面的评论)。
  • 据我了解,AVX CPUID 功能位意味着支持每条 SSE、SSE2、SSE3、SSSE3、SSE4.1 和 SSE4.2 指令的 VEX 编码 128b 版本。请注意英特尔手册如何说VAESDEC 需要AVX & AES 功能标志,但VPHADDD xmm1, xmm2, xmm3/m128 只是说你需要AVX,而不是AVX & SSSE3,例如。
猜你喜欢
  • 2012-05-17
  • 2013-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-06
  • 2015-04-06
  • 2012-03-16
相关资源
最近更新 更多