如何将 2 个 16 位向量相乘并将结果存储在 sse 中的 32 位向量中?
How to Multiply 2 16 bit vectors and store result in 32 bit vector in sse?
由于溢出问题,我需要乘以 2 个 16 位向量并希望得到 32 位向量的输出。
A = [ 1, 2, 3, 4, 5, 6, 7, 8]
B = [ 1, 3, 5, 6, 8, 9, 10 ,12 ]
C1= [ 1*1 + 2*3, 3*5, 4*6]
c2= [ 5*8, 6* 9, 7*10, 8*12 ]
我能够通过首先将 A 和 B 分成 32 位向量然后使用下面的乘法函数来做到这一点
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 */
}
但我认为这效率不高,我们可以使用 _mm_mullo_epi16
来提高效率。有人可以 suggest/post 实现这个的代码吗?
是的,你可以这样做:
static inline void muly(__m128i &vh, __m128i &vl, // output - 2x4xint32_t
const __m128i v0, const __m128i v1) // input - 2x8xint16_t
const __m128i vhi = _mm_mulhi_epi16(v0, v1); // mul lo
const __m128i vlo = _mm_mullo_epi16(v0, v1); // mul hi
vh = _mm_unpackhi_epi16(vlo, vhi); // interleave results
vl = _mm_unpacklo_epi16(vlo, vhi);
}
请注意,对于 16x16 乘法,您可能需要考虑使用定点乘法。这种方法通常用于 DSP 和图像处理任务,例如过滤。它比完整的 16x16->32 乘法更有效,并且还避免了数据扩展和缩小到 16 位的需要。
由于溢出问题,我需要乘以 2 个 16 位向量并希望得到 32 位向量的输出。
A = [ 1, 2, 3, 4, 5, 6, 7, 8]
B = [ 1, 3, 5, 6, 8, 9, 10 ,12 ]
C1= [ 1*1 + 2*3, 3*5, 4*6]
c2= [ 5*8, 6* 9, 7*10, 8*12 ]
我能够通过首先将 A 和 B 分成 32 位向量然后使用下面的乘法函数来做到这一点
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 */
}
但我认为这效率不高,我们可以使用 _mm_mullo_epi16
来提高效率。有人可以 suggest/post 实现这个的代码吗?
是的,你可以这样做:
static inline void muly(__m128i &vh, __m128i &vl, // output - 2x4xint32_t
const __m128i v0, const __m128i v1) // input - 2x8xint16_t
const __m128i vhi = _mm_mulhi_epi16(v0, v1); // mul lo
const __m128i vlo = _mm_mullo_epi16(v0, v1); // mul hi
vh = _mm_unpackhi_epi16(vlo, vhi); // interleave results
vl = _mm_unpacklo_epi16(vlo, vhi);
}
请注意,对于 16x16 乘法,您可能需要考虑使用定点乘法。这种方法通常用于 DSP 和图像处理任务,例如过滤。它比完整的 16x16->32 乘法更有效,并且还避免了数据扩展和缩小到 16 位的需要。