Умножение SSE на 4 32-битных целых числа

Как умножить четыре 32-битных целых числа на 4 целых числа? Я не нашел инструкции, которая может это сделать.

Ответы

Ответ 1

Если вам нужно скопировать 32-битное целочисленное умножение, то следующий пример в 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 */
}

Возможно, у вас есть две сборки: одна для старых процессоров и одна для последних процессоров, и в этом случае вы можете сделать следующее:

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
}

Ответ 2

PMULLD, из SSE 4.1, делает это.

Описание немного вводит в заблуждение, оно говорит о подписанном умножении, но поскольку оно хранит только младшие 32 бита, это действительно незаметная инструкция, которую вы можете использовать для обоих, так же, как IMUL.