gpt4 book ai didi

c - 如何使用 SSE 进行 uint32/float 转换?

转载 作者:太空狗 更新时间:2023-10-29 17:06:37 25 4
gpt4 key购买 nike

在 SSE 中有一个函数 _mm_cvtepi32_ps(__m128i input) 接受 32 位宽有符号整数 (int32_t) 的输入 vector 并将它们转换为 floats.

现在,我想将输入整数解释为未签名。但是没有函数 _mm_cvtepu32_ps 并且我找不到一个实现。你知道我在哪里可以找到这样的功能或者至少给出实现的提示吗?为了说明结果的差异:

unsigned int a = 2480160505; // 10010011 11010100 00111110 11111001   
float a1 = a; // 01001111 00010011 11010100 00111111;
float a2 = (signed int)a; // 11001110 11011000 01010111 10000010

最佳答案

使用 Paul R 的解决方案和我之前的解决方案四舍五入后的 float 与原整数之差小于等于0.75 ULP(排在最后的单位)。在这些方法中在两个地方可能会发生舍入:在 _mm_cvtepi32_ps 和在 _mm_add_ps 中。这会导致某些输入的结果不是尽可能准确。

例如,使用 Paul R 的方法 0x2000003=33554435 被转换为 33554432.0,但是 33554436.0也作为 float 存在,在这里会更好。我以前的解决方案也存在类似的错误。这种不准确的结果也可能出现在编译器生成的代码中,see here .

按照gcc的方法(see Peter Cordes' answer to that other SO question) ,得到0.5 ULP以内的准确转换:

inline __m128 _mm_cvtepu32_ps(const __m128i v)
{
__m128i msk_lo = _mm_set1_epi32(0xFFFF);
__m128 cnst65536f= _mm_set1_ps(65536.0f);

__m128i v_lo = _mm_and_si128(v,msk_lo); /* extract the 16 lowest significant bits of v */
__m128i v_hi = _mm_srli_epi32(v,16); /* 16 most significant bits of v */
__m128 v_lo_flt = _mm_cvtepi32_ps(v_lo); /* No rounding */
__m128 v_hi_flt = _mm_cvtepi32_ps(v_hi); /* No rounding */
v_hi_flt = _mm_mul_ps(cnst65536f,v_hi_flt); /* No rounding */
return _mm_add_ps(v_hi_flt,v_lo_flt); /* Rounding may occur here, mul and add may fuse to fma for haswell and newer */
} /* _mm_add_ps is guaranteed to give results with an error of at most 0.5 ULP */

注意其他高位/低位分区也是可以的,只要_mm_cvt_ps可以转换两件都 float 而不四舍五入。例如,具有 20 个高位和 12 个低位的分区将同样有效。

关于c - 如何使用 SSE 进行 uint32/float 转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34066228/

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