以可移植的方式访问 __m128i 变量的字段
Accessing the fields of a __m128i variable in a portable way
我正在尝试使用 SIMD 指令来加速 uint8_t 数组中元素的总和(即,求和)。为此,我复制了这个问题中投票最多的答案:
Sum reduction of unsigned bytes without overflow, using SSE2 on Intel
该答案中显示的总和减少程序是这样的:
uint16_t sum_32(const uint8_t a[32])
{
__m128i zero = _mm_xor_si128(zero, zero);
__m128i sum0 = _mm_sad_epu8(
zero,
_mm_load_si128(reinterpret_cast<const __m128i*>(a)));
__m128i sum1 = _mm_sad_epu8(
zero,
_mm_load_si128(reinterpret_cast<const __m128i*>(&a[16])));
__m128i sum2 = _mm_add_epi16(sum0, sum1);
__m128i totalsum = _mm_add_epi16(sum2, _mm_shuffle_epi32(sum2, 2));
return totalsum.m128i_u16[0];
}
我的问题是 return 操作 (totalsum.m128i_u16[0]
) 似乎只适用于 Microsoft,但我使用的是基于 UNIX 的平台。
我查看了 SIMD 内部函数列表,函数 _mm_storeu_ps(a, t)
似乎做的事情与我要求的类似,但 t
必须是一个 __m128 变量和一个 a
浮动。我试图通过将我的结果从 __m128i 转换为 __m128 来使用该函数,但它没有用。
是否有另一种方法可以检索 __m128i 变量的前 16 位并将它们存储到 uint16_t 变量中?我是 SIMD 编程的新手。
顺便说一句,有没有更好的解决方案来实现和减少?。这个答案是9年前的。我想现在是更好的选择。
_mm_extract_epi16
compile-time 已知索引。
对于第一个元素_mm_cvtsi128_si32
给出了更有效的指令。这会起作用,因为:
_mm_sad_epu8
将位 16 到 63 填充为零
- 您通过
uint16_t
return type 将结果截断为 16 位
编译器可能会根据其中一个原因自行进行此优化,但不是全部,因此最好使用 _mm_cvtsi128_si32
.
我正在尝试使用 SIMD 指令来加速 uint8_t 数组中元素的总和(即,求和)。为此,我复制了这个问题中投票最多的答案:
Sum reduction of unsigned bytes without overflow, using SSE2 on Intel
该答案中显示的总和减少程序是这样的:
uint16_t sum_32(const uint8_t a[32])
{
__m128i zero = _mm_xor_si128(zero, zero);
__m128i sum0 = _mm_sad_epu8(
zero,
_mm_load_si128(reinterpret_cast<const __m128i*>(a)));
__m128i sum1 = _mm_sad_epu8(
zero,
_mm_load_si128(reinterpret_cast<const __m128i*>(&a[16])));
__m128i sum2 = _mm_add_epi16(sum0, sum1);
__m128i totalsum = _mm_add_epi16(sum2, _mm_shuffle_epi32(sum2, 2));
return totalsum.m128i_u16[0];
}
我的问题是 return 操作 (totalsum.m128i_u16[0]
) 似乎只适用于 Microsoft,但我使用的是基于 UNIX 的平台。
我查看了 SIMD 内部函数列表,函数 _mm_storeu_ps(a, t)
似乎做的事情与我要求的类似,但 t
必须是一个 __m128 变量和一个 a
浮动。我试图通过将我的结果从 __m128i 转换为 __m128 来使用该函数,但它没有用。
是否有另一种方法可以检索 __m128i 变量的前 16 位并将它们存储到 uint16_t 变量中?我是 SIMD 编程的新手。
顺便说一句,有没有更好的解决方案来实现和减少?。这个答案是9年前的。我想现在是更好的选择。
_mm_extract_epi16
compile-time 已知索引。
对于第一个元素_mm_cvtsi128_si32
给出了更有效的指令。这会起作用,因为:
_mm_sad_epu8
将位 16 到 63 填充为零- 您通过
uint16_t
return type 将结果截断为 16 位
编译器可能会根据其中一个原因自行进行此优化,但不是全部,因此最好使用 _mm_cvtsi128_si32
.