除法和LUT? /快速浮动分割互惠

时间:2012-09-01 10:53:16

标签: c++ c optimization fpu

是否可以在形式上进行浮动除法的倒数 查找表(如1 / f - > 1 * inv [f])?怎么做? 我认为应该将一些和掩盖和移位应用于浮动 它是一种索引形式?怎么会这样呢?

3 个答案:

答案 0 :(得分:6)

你可以猜出这样的近似逆:

int x = reinterpret_cast<int>(f);
x = 0x7EEEEEEE - x;
float inv = reinterpret_cast<float>(x);

在我的测试中,0x7EF19D07略好一些(测试了包含2个Newton-Raphson改进的效果)。

然后您可以使用Newton-Raphson进行改进:

inv = inv * (2 - inv * f);

根据需要随时迭代。 2或3次迭代可以得到很好的结果。

更好的初始近似值

最小化相对误差:

  • 0x7EF311C2(未经细化)
  • 0x7EF311C3(1个细化)
  • 0x7EF312AC(2个改进)
  • 0x7EEEEBB3(3个改进)

最小化1到2之间输入的绝对误差(它们在该范围之外运行良好,但它们可能不是最好的):

  • 0x7EF504F3(未经细化)
  • 0x7EF40D2F(1个细化)
  • 0x7EF39252(2个改进)

对于三个细化步骤,初始近似几乎不影响最大相对误差。 0x7EEEEEEE运行良好,我找不到更好的东西。

答案 1 :(得分:3)

一种方法是:

  1. 从输入
  2. 中提取符号,指数和尾数
  3. 使用一些最重要的尾数位在表格中查找其倒数
  4. 取消指数,并调整尾数的比例变化
  5. 重新组合符号,指数和尾数以形成输出
  6. 在第2步中,您需要选择要使用的位数,在准确度和表格大小之间进行交易。通过使用较低有效位在表条目之间进行插值,可以获得更高的精度。

    在步骤3中,调整是必要的,因为输入尾数在范围(0.5,1.0)内,因此其倒数在[1.0,2.0]范围内,需要重新正规化以给出输出尾数。

    我不会尝试为此编写代码,因为我可能会错过一些稍微偏僻的边缘情况。

    您还应该研究涉及数值计算的方法,如果内存访问速度慢,可能会产生更好的结果;在现代PC架构中,缓存未命中可能与几十个算术运算一样昂贵。 Wikipedia看起来是一个很好的起点。当然,无论你做什么,都要测量它以确保它实际上比FPU除法操作更快。

答案 2 :(得分:0)

如果你的最小步长是0.01,那么你可以从表中支持inverse-f。每个索引都乘以100,因此您可以

table[1]----->1.0/0.01
table[3]----->1.0/0.03
table[105]--->1.0/1.05
...
table[10000]->1.0/100.0


10000 elements for a range of (0.00,100.00)

如果你想要更高的精度,你需要更多的ram。

另一个例子:

range................: 0.000 - 1000.000
minimum increments ..: 0.001
total element number.: 1 million

something like this: table[2343]=1.0/2.343

另一个例子:

range................: 0.000000 - 1.000000
minimum increments ..: 0.000001
total element number.: 1 million

something like this: table[999999]=1.0/0.999999