我正在编写一个用于统计抽样的小型库,需要尽可能快地运行。在分析中,我发现函数中大约40%的时间用于计算Stirling's approximation的阶乘对数。我正在将优化工作集中在这部分上。这是我的代码(使用MPFR):
const double AL[8] =
{ 0.0, 0.0, 0.6931471806, 1.791759469, 3.178053830, 4.787491743,
6.579251212, 8.525161361 };
void HGD::mpfr_afc(mpfr_t &ret, const mpfr_t &val){
if(mpfr_cmp_ui(val, 7) <= 0){
mpfr_set_d(ret, AL[mpfr_get_ui(val, MPFR_RNDN)], MPFR_RNDN);
}else{
mpfr_set(ret, val, MPFR_RNDN);
mpfr_add_d(ret, ret, 0.5, MPFR_RNDN);
mpfr_log(LV, val, MPFR_RNDN);
mpfr_mul(ret, LV, ret, MPFR_RNDN);
mpfr_sub(ret, ret, val, MPFR_RNDN);
mpfr_add_d(ret, ret, 0.399089934, MPFR_RNDN);
}
}
我有几个不同的想法:
我可以采取其他方法吗?
答案 0 :(得分:2)
当数字适合机器数据类型时切换到本机算术
这将是我的第一次尝试。 MPFR可能是性能杀手。
在我看来,你想要计算n的对数!你已经接近斯特林的公式了。
注意n!= Gamma(n + 1)。有(看似)高度优化的函数来计算Gamma函数及其对数。例如:
只有在以上所有情况都失败的情况下,我才会推出自己的粗略近似值。
答案 1 :(得分:1)
这里有几点想法。首先,我发现使用MPFR可能会有点过分。任何多精度库都有巨大的开销。不仅需要大量开销,还需要巨大的开销。第二个想法是,您可能不需要使用多精度日志功能。也许你可以逃脱标准日志?
如果你不能在双精度浮点数中拟合你的计算,那么使用线程或其他方法进行并行化肯定会有所帮助。您可以尝试使用编译器优化,但我没有看到真正的改进尝试。
您可以尝试的最后一个选项是手动分配内存空间,以便MPFR具有固定的开销。我从未尝试过,所以我不知道它是否会有所帮助。