0

我有一个 NEON 寄存器,里面填满了float32. 我想将它们四舍五入到最接近的整数,而不必传输回主 CPU。NEON 指令转换float32uint32简单截断,因此例如39.7变为39,而不是40。我不太关心如何0.5处理——从零舍入或舍入到甚至两者都对我有用。

我可以看到实现舍入的最佳途径是

  • 转换为int32(因此截断)
  • 转换_float32
  • 将 1 添加到int32,转换回float32,并留出以防我们四舍五入
  • 减去
  • 比较0.5(不需要绝对值,因为我知道在我的情况下它们都是积极的)
  • 根据比较结果选择 truncated 或 truncated + 1

这看起来丑陋、缓慢和复杂。

有没有更清洁、更快、更简单、更理智的方法?

4

2 回答 2

7

添加 .5 并转换为整数。如果您想要浮点格式的结果,请转换回来。

由于您知道这些数字都是正数,因此另一种选择是加 0x1p23 并减去 0x1p23。加上 0x1p23 的结果至少是 0x1p23,所以浮点结果没有小于 1 的位,所以它肯定已经四舍五入为整数。然后减去 0x1p23 减去添加的值,只留下四舍五入的效果。

更新:如果输入在 [0x1p47, 0x1p48) 并且其低位为 1,则第二种方法将失败。那么 0x1p23 是输入的 ULP 的一半,所以加法会导致向上舍入(到偶数),而减法没有效果。我认为有一个修改可以解决这个问题,但我手头没有。

于 2012-05-26T01:12:20.227 回答
0

我们知道,浮点数到整数轮次需要根据正数或负数加减 0.5。在 Neon 中, 1. 我可以提取有符号的值;2. 与0.5位或,则0.5有符号;3. 添加有符号的 0.5 和原始值:

// 1. extract sign of origin value
int32x4_t reinterpretInt = vreinterpretq_s32_f32(inputFloat);
int32x4_t signExtract = vdupq_n_s32(-2147483648);
int32x4_t signSignal = vandq_s32(reinterpretInt, signExtract);

// 2. bit-or with 0.5 with origin value
float32x4_t roundValue = vdupq_n_f32(0.5);
float32x4_t plusValue = vreinterpretq_f32_s32(vorrq_s32(vreinterpretq_s32_f32(roundValue), signSignal));

// 3. add signed 
return vaddq_f32(inputFloat, plusValue);
于 2018-08-16T10:00:00.533 回答