高效 10 倍的功率
Efficient 10 to the power double
我必须多次计算 10 的 2 次方。
有没有比数学库更有效的方法pow(10,double)
?如果重要的话,我的双打在-5和-11之间总是负数。
我假设 pow(double,double) 使用比 pow(10,double) 所需的更通用的算法,因此可能不是最快的方法。鉴于下面的一些答案,这可能是一个错误的假设。
至于为什么,是为了对数插值。
我有一个 table 的 x 和 y 值。
我的对象有一个已知的 x 值(几乎总是双精度值)。
double Dbeta(struct Data *diffusion, double per){
double frac;
while(per>diffusion->x[i]){
i++;
}
frac = (per-diffusion->x[i-1])/(diffusion->x[i]-diffusion->x[i-1]);
return pow(10,log10DB[i-1] + frac * (log10DB[i]-log10DB[i-1]));
}
这个函数被调用了很多次。
我被告知要研究分析,所以这是我首先要做的。
我刚刚被告知我可以使用自然对数而不是以 10 为底数,这显然是正确的。 (我的愚蠢有时甚至让我自己感到惊讶。)
用自然对数替换所有内容后,一切运行得都快了一点。通过分析(这是我今天学到的一个新词),我发现我的代码有 39% 花在了 exp 函数上,所以对于那些想知道是否这部分实际上是我的代码瓶颈的人来说,确实是。
对于pow(10.0, n)
,设置c = log(10.0)
应该更快,你可以计算一次,然后使用exp(c*n)
,这应该比pow(10.0, n)
快得多(基本上在内部做同样的事情,除了它会一遍又一遍地计算 log(10.0)
而不是一次)。除此之外,您可能无能为力。
是的,pow 函数很慢(对于那些要求基准测试的人来说,大约是乘法成本的 50 倍)。
通过一些log/exponents技巧,我们可以将 10^x 表示为
10^x = exp(log(10^x)) = exp(x * log(10)).
所以你可以用exp(x * M_LN10)
实现10^x,这应该比pow更有效率。
如果双精度不是关键,请使用函数的浮点版本 expf
(或 powf
),这应该比双精度版本更有效。
如果粗略精度没问题,预先计算 [-5, -11] 范围内的 table 并使用线性插值快速查找。
一些基准测试(使用 glibc 2.31):
Benchmark Time
---------------------------------
pow(10, x) 15.54 ns
powf(10, x) 7.18 ns
expf(x * (float)M_LN10) 3.45 ns
我必须多次计算 10 的 2 次方。
有没有比数学库更有效的方法pow(10,double)
?如果重要的话,我的双打在-5和-11之间总是负数。
我假设 pow(double,double) 使用比 pow(10,double) 所需的更通用的算法,因此可能不是最快的方法。鉴于下面的一些答案,这可能是一个错误的假设。
至于为什么,是为了对数插值。 我有一个 table 的 x 和 y 值。 我的对象有一个已知的 x 值(几乎总是双精度值)。
double Dbeta(struct Data *diffusion, double per){
double frac;
while(per>diffusion->x[i]){
i++;
}
frac = (per-diffusion->x[i-1])/(diffusion->x[i]-diffusion->x[i-1]);
return pow(10,log10DB[i-1] + frac * (log10DB[i]-log10DB[i-1]));
}
这个函数被调用了很多次。 我被告知要研究分析,所以这是我首先要做的。
我刚刚被告知我可以使用自然对数而不是以 10 为底数,这显然是正确的。 (我的愚蠢有时甚至让我自己感到惊讶。)
用自然对数替换所有内容后,一切运行得都快了一点。通过分析(这是我今天学到的一个新词),我发现我的代码有 39% 花在了 exp 函数上,所以对于那些想知道是否这部分实际上是我的代码瓶颈的人来说,确实是。
对于pow(10.0, n)
,设置c = log(10.0)
应该更快,你可以计算一次,然后使用exp(c*n)
,这应该比pow(10.0, n)
快得多(基本上在内部做同样的事情,除了它会一遍又一遍地计算 log(10.0)
而不是一次)。除此之外,您可能无能为力。
是的,pow 函数很慢(对于那些要求基准测试的人来说,大约是乘法成本的 50 倍)。
通过一些log/exponents技巧,我们可以将 10^x 表示为
10^x = exp(log(10^x)) = exp(x * log(10)).
所以你可以用
exp(x * M_LN10)
实现10^x,这应该比pow更有效率。如果双精度不是关键,请使用函数的浮点版本
expf
(或powf
),这应该比双精度版本更有效。如果粗略精度没问题,预先计算 [-5, -11] 范围内的 table 并使用线性插值快速查找。
一些基准测试(使用 glibc 2.31):
Benchmark Time
---------------------------------
pow(10, x) 15.54 ns
powf(10, x) 7.18 ns
expf(x * (float)M_LN10) 3.45 ns