【发布时间】:2012-05-17 01:31:54
【问题描述】:
如何将四个 32 位整数乘以另外 4 个整数? 我没有找到任何可以做到这一点的指令。
【问题讨论】:
标签: x86 sse simd multiplication sse2
如何将四个 32 位整数乘以另外 4 个整数? 我没有找到任何可以做到这一点的指令。
【问题讨论】:
标签: x86 sse simd multiplication sse2
PMULLD,来自 SSE 4.1,就是这样做的。
描述有点误导,它谈到有符号乘法,但由于它只存储低 32 位,所以它确实是一个符号忽略指令,你可以同时使用它,就像 IMUL。
【讨论】:
_mm_mullo_epi32 如果您更愿意使用内部函数而不是原始程序集
imul 可能更快更简单
如果您需要有符号 32x32 位整数乘法,那么software.intel.com 的以下示例看起来应该可以满足您的需求:
static inline __m128i muly(const __m128i &a, const __m128i &b)
{
__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 */
return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0))); /* shuffle results to [63..0] and pack */
}
您可能希望有两个构建 - 一个用于旧 CPU,一个用于最近的 CPU,在这种情况下,您可以执行以下操作:
static inline __m128i muly(const __m128i &a, const __m128i &b)
{
#ifdef __SSE4_1__ // modern CPU - use SSE 4.1
return _mm_mullo_epi32(a, b);
#else // old CPU - use SSE 2
__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 */
return _mm_unpacklo_epi32(_mm_shuffle_epi32(tmp1, _MM_SHUFFLE (0,0,2,0)), _mm_shuffle_epi32(tmp2, _MM_SHUFFLE (0,0,2,0))); /* shuffle results to [63..0] and pack */
#endif
}
【讨论】:
__MNI__、__SNI__ 等 - 主要是出于历史原因,但它也不太容易出现上述简单错误.
_mm_insert_epi32...
for 循环要慢 - 在我的机器上肯定不会更快。