如何使用intrinsics以元素方式将两个char数组相乘并将乘法加总为int?

时间:2016-10-17 12:03:16

标签: c++ algorithm x86-64 simd intrinsics

我不熟悉x86_64内在函数,我想使用256位向量寄存器进行以下操作。 我正在使用_mm256_maddubs_epi16(a,b);但是,由于char * char可能超过16位最大值,因此该指令似乎存在溢出问题。我有问题了解_mm256_unpackhi_epi32及相关说明。

任何人都可以详细说明并向我展示目的地的光吗?谢谢!

int sumup_char_arrays(char *A, char *B, int size) {
    assert (size % 32 == 0);
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += A[i]*B[i];
    }
    return sum;
}

1 个答案:

答案 0 :(得分:1)

我已经找到了解决方案,任何改进它的想法,特别是减少的最后阶段。

int sumup_char_arrays(char *A, char *B, int size) {
    assert (size % 32 == 0);
    int sum = 0;
    __m256i sum_tmp;
    for (int i = 0; i < size; i += 32) {
        __m256i ma_l = _mm256_cvtepi8_epi16(_mm_load_si128((__m128i*)A));
        __m256i ma_h = _mm256_cvtepi8_epi16(_mm_load_si128((__m128i*)(A+16)));
        __m256i mb_l = _mm256_cvtepi8_epi16(_mm_load_si128((__m128i*)B));
        __m256i mb_h = _mm256_cvtepi8_epi16(_mm_load_si128((__m128i*)(B+16)));
        __m256i mc = _mm256_madd_epi16(ma_l, mb_l);
        mc = _mm256_add_epi32(mc, _mm256_madd_epi16(ma_h, mb_h));
        sum_tmp = _mm256_add_epi32(mc, sum_tmp);
        //sum += A[i]*B[i];
    }
    sum_tmp = _mm256_add_epi32(sum_tmp, _mm256_permute2x128_si256(sum_tmp, sum_tmp, 0x81));
    sum_tmp = _mm256_add_epi32(sum_tmp, _mm256_srli_si256(sum_tmp, 8));
    sum_tmp = _mm256_add_epi32(sum_tmp, _mm256_srli_si256(sum_tmp, 4));        
    sum = _mm256_extract_epi32(sum_tmp, 0);
    return sum;
}