使用NEON进行矢量化浮点舍入

时间:2012-05-26 00:06:03

标签: floating-point arm rounding neon

我有一个充满float32的NEON寄存器。我想将它们四舍五入到最接近的整数,而不必转回主CPU。将float32转换为uint32的NEON指令只是截断,例如39.7变为39,而不是40。我并不关心0.5如何处理 - 从零或圆到圆,甚至两者都适合我。

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

  • 转换为int32(因此截断)
  • 转换回float32
  • int32添加1,转换回float32,并留出以防万一我们正在整理
  • 减去
  • 0.5比较(不需要abs值,因为我知道在我的情况下他们都是正面的)
  • 根据比较结果选择截断或截断+ 1

这看起来很丑陋,缓慢而复杂。

是否有更清洁,更快捷,更简洁,更健全的方式?

2 个答案:

答案 0 :(得分:6)

添加.5并转换为整数。如果希望结果采用浮点格式,请转换回来。

由于您知道数字都是正数,因此另一个选项是添加0x1p23并减去0x1p23。添加0x1p23的结果至少为0x1p23,因此float结果没有值小于1的位,因此它必须舍入为整数。然后减去0x1p23减去添加的值,只留下舍入的效果。

答案 1 :(得分: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);