我正在尝试使用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。