gpt4 book ai didi

x86 - 添加饱和的 32 位带符号整数内在函数?

转载 作者:行者123 更新时间:2023-12-04 14:40:50 26 4
gpt4 key购买 nike

有人可以推荐一种使用 Intel 内在函数(AVX、SSE4 ...)添加饱和 32 位带符号整数的快速方法吗?

我查看了内在函数指南并找到了 _mm256_adds_epi16 但这似乎只能添加 16 位整数。对于 32 位,我没有看到任何类似的东西。其他调用似乎环绕。

最佳答案

如果(且仅当)发生签名溢出:

  • 两个输入的符号相同,并且
  • 总和的符号(添加环绕时)与输入不同

使用 C 运算符:overflow = ~(a^b) & (a^(a+b))

此外,如果发生溢出,饱和结果将与任一输入具有相同的符号。使用@PeterCordes 建议的 int_min = int_max+1 技巧,并假设您至少有 SSE4.1(对于 blendvps)这可以实现为:

__m128i __mm_adds_epi32( __m128i a, __m128i b )
{
const __m128i int_max = _mm_set1_epi32( 0x7FFFFFFF );

// normal result (possibly wraps around)
__m128i res = _mm_add_epi32( a, b );

// If result saturates, it has the same sign as both a and b
__m128i sign_bit = _mm_srli_epi32(a, 31); // shift sign to lowest bit
__m128i saturated = _mm_add_epi32(int_max, sign_bit);

// saturation happened if inputs do not have different signs,
// but sign of result is different:
__m128i sign_xor = _mm_xor_si128( a, b );
__m128i overflow = _mm_andnot_si128(sign_xor, _mm_xor_si128(a,res));

return _mm_castps_si128(_mm_blendv_ps( _mm_castsi128_ps( res ),
_mm_castsi128_ps(saturated),
_mm_castsi128_ps( overflow ) ) );
}

如果您的 blendvps 与移位和加法一样快(或更快)(还要考虑端口使用情况),您当然可以混合 int_minint_max,符号位为a。此外,如果您只有 SSE2 或 SSE3,则可以通过向右算术移位(溢出)31 位和手动混合(使用 and/andnot/or)来替换最后的混合。

当然,对于 AVX2,这可以使用 __m256i 变量而不是 __m128i(应该很容易重写)。

附录 如果你在编译时知道ab的符号,你可以直接设置saturated 相应地,您可以同时保存 _mm_xor_si128 计算,即 overflow 对于正 a 将是 _mm_andnot_si128(b, res) _mm_andnot(res, b) 用于负 a(res = a+b)。

测试用例/演示:https://godbolt.org/z/v1bsc85nG

关于x86 - 添加饱和的 32 位带符号整数内在函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29498824/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com