我正在尝试使用32位整数对非常长的二进制向量进行按位或运算。

在此示例中,我们可以假设nwords是单词数,并且是4和8的倍数。因此,没有循环提示。该二进制向量可以包含数千个位。

此外,分别针对SSE2和AVX2使用_align_malloc()以16位和18位对齐的方式分配所有三个位向量。

令我惊讶的是,以下三个标量,SSE2和AVX2代码在i7 CPU上使用的时间完全相同。我没有体验到SSE2和AVX2寄存器的预期x4和x8加速。

我的MVisual Studio版本是15.1。

标量代码:

void vectorOr_Scalar(unsigned int *ptr1, unsigned int *ptr2, unsigned int *out, int nwords)
{
    for (end = ptr1 + nwords; ptr1 < end; ptr1++, ptr2++, out++) *out = *ptr1 | *ptr2;
}


SSE2代码:

void vectorOr_SSE2(unsigned int *ptr1, unsigned int *ptr2, unsigned int *out, int nwords)
{
    for (i = 0; i < nwords; i += 4, ptr1 += 4, ptr2 += 4, out += 4)
    {
        __m128i v1 = _mm_load_si128((__m128i *)ptr1);
        __m128i v2 = _mm_load_si128((__m128i *)ptr2);
        _mm_store_si128((__m128i *)out, _mm_or_si128(v1, v2));
    }
}


AVX2代码:

void vectorOr_AVX2(unsigned int *ptr1, unsigned int *ptr2, unsigned int *out, int nwords)
{
    for (i = 0; i < nwords; i += 8, ptr1 += 8, ptr2 += 8, out += 8)
    {
        __m256i v1 = _mm256_load_si256((__m256i *)ptr1);
        __m256i v2 = _mm256_load_si256((__m256i *)ptr2);
        _mm256_store_si256((__m256i *)out, _mm256_or_si256(v1, v2));
    }
}


由于加载和存储之间的寄存器操作数量有限,此应用程序可能不适用于矢量化吗?

最佳答案

您没有观察到一次处理一个unsigned的循环与一次处理8个unsigned的SIMD循环之间的性能差异的原因是,因为编译器会为您生成SIMD代码并展开该循环,请参见the generated assembly

09-05 01:37