我正在开发一种能够为物理和渲染调用许多数学函数的游戏。已知Quake3中使用的"Fast inverse sqrt"比sqrt()快,并且它的背景很漂亮。
您是否知道任何其他算法比平时更快且准确度损失可接受?
答案 0 :(得分:13)
任何连续函数(包括最常见的数学运算)都可以通过多项式在有界区间内很好地近似。这与常见数学函数通常满足的相对简单的标识(如加法则)和表查找一起,提供了构建快速逼近算法的标准技术的基础(以及系统数学中使用的高精度方法的基础)。库)。
然而,泰勒系列通常是一个糟糕的选择;对于大多数计算用途,Chebyshev或Minimax多项式具有更好的误差特性。拟合minimax多项式的标准技术是使用Remes的算法,该算法在很多商业数学软件中实现,或者如果你知道你正在做什么,你可以用一天的工作来完成你自己的实现。为了记录,在现代处理器上应该避免使用“快速反平方根”,因为使用浮点倒数平方根估计指令(rsqrtss
/ rsqrtps
要快得多SSE,NEON上的vrsqrte
,AltiVec上的vrsqrtefp
。即使是(非近似)硬件平方根在当前的英特尔处理器上速度也非常快。
答案 1 :(得分:9)
这些算法在文献中称为“近似算法”。有大量例子的标准书是Approximation Algorithms by Vijay V. Vazirani。
sin x ~~ x的情况是稍微更一般的特例:查看函数的Taylor series(或周期函数的傅里叶级数)并仅计算前几个项。
另一种(有点残酷的)技术是随机组合你的函数的几个点,然后对它进行线性回归。这样,你也可以得到一个很好的多项式来描述你的函数:)。
答案 2 :(得分:5)
对于小x:sin(x)〜= x是经常在物理中使用的
答案 3 :(得分:3)
Niko有一些很好的建议,我会添加旧时尚查找表。
我在高性能实时系统中成功地多次使用查找表来查找循环函数(sin / cos / tan)。 sqrt()更难以这种方式,但是如果您的输入范围受到限制(比如屏幕像素)则很难超越速度,您可以精确地调整空间/准确度。你也可以使用查找一个公共范围,然后对一个罕见的情况下框架sqrt()函数的余量。
保罗答案 4 :(得分:2)
从Doom源代码中,可以获得两个2D点之间的近似距离,而无需使用sqrt()或三角函数:
fixed_t P_AproxDistance(fixed_t dx, fixed_t dy )
{
dx = abs(dx);
dy = abs(dy);
if (dx < dy)
return dx+dy-(dx>>1);
else
return dx+dy-(dy>>1);
}
请注意x >> 1
与x / 2
相同,但速度稍快 - 现代好的编译器会自动执行此操作,但当时它们并不是那么好。
答案 5 :(得分:1)
任何概率通常都是这样的。运行模拟10次会更快,但产生的结果不如运行模拟1000次。