接近log10 [x ^ k0 + k1]

Yal*_*ang 11 math optimization sse simd approximation

问候.我正在尝试近似函数

Log10 [x ^ k0 + k1],其中.21 <k0 <21,0 <k1 <~2000,并且x是整数<2 ^ 14.

k0和k1是不变的.出于实际目的,可以假设k0 = 2.12,k1 = 2660.期望的精度是5*10 ^ -4相对误差.

这个函数实际上与Log [x]相同,除了0附近,它有很大的不同.

我已经提出了一个比简单查找表快1.15倍的SIMD实现,但是如果可能的话我想改进它,我认为由于缺乏有效的指令而非常困难.

我的SIMD实现使用16位定点算法来评估三次多项式(我使用最小二乘拟合).多项式对不同的输入范围使用不同的系数.有8个范围,范围i跨越(64)2 ^ i到(64)2 ^(i + 1).这背后的理性是Log [x]的导数随x快速下降,这意味着多项式将更准确地拟合它,因为多项式非常适合于具有超出某个阶的0的导数的函数.

使用单个_mm_shuffle_epi8()可以非常有效地完成SIMD表查找.我使用SSE的float到int转换来获得指数和有效数,用于固定点近似.我还通过软件管道化循环以获得~1.25倍的加速,因此可能不太可能进行进一步的代码优化.

我要问的是,如果在更高的水平上有更高效的近似值?例如:

  1. 可以将此函数分解为具有有限域的函数,如log2((2 ^ x)*significand)= x + log2(有效数字)

因此消除了处理不同范围(表查找)的需要.我认为的主要问题是添加k1术语会杀死我们所知道和喜爱的所有那些不错的日志属性,这使得它无法实现.或者是吗?

  1. 迭代方法?不要这么认为,因为log [x]的牛顿方法已经是一个复杂的表达式

  2. 利用邻近像素的局部性? - 如果8个输入的范围落在相同的近似范围内,那么我可以查找单个系数,而不是查找每个元素的单独系数.因此,我可以将其用作快速常见的情况,并在不使用时使用较慢的通用代码路径.但是对于我的数据,在该属性保持70%的时间之前,范围需要大约2000,这似乎不会使这种方法具有竞争力.

请给我一些意见,特别是如果你是一名应用数学家,即使你说它不能完成.谢谢.

小智 2

一个观察结果:您可以找到一个表达式来表示 x 需要多大,作为 k0 和 k1 的函数,使得 x^k0 项足以主导 k1 以进行近似:

x^k0 +k1 ~= x^k0,允许您将函数近似评估为

k0*Log(x)。

这将处理所有高于某个值的 x。