我需要非常快速地计算斯特林的近似值

时间:2014-02-12 03:05:42

标签: c++ c numerical arbitrary-precision mpfr

我正在编写一个用于统计抽样的小型库,需要尽可能快地运行。在分析中,我发现函数中大约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);
    }
}

我有几个不同的想法:

  • 预计算超过函数的前8个输入。
  • 优化数学运算(使用较粗略的近似值以获得较小的精度)
  • 使用多个线程并行计算不同输入
  • 当数字适合机器数据类型时切换到本机算法

我可以采取其他方法吗?

2 个答案:

答案 0 :(得分:2)

  

当数字适合机器数据类型时切换到本机算术

这将是我的第一次尝试。 MPFR可能是性能杀手。

在我看来,你想要计算n的对数!你已经接近斯特林的公式了。

注意n!= Gamma(n + 1)。有(看似)高度优化的函数来计算Gamma函数及其对数。例如:

只有在以上所有情况都失败的情况下,我才会推出自己的粗略近似值。

答案 1 :(得分:1)

这里有几点想法。首先,我发现使用MPFR可能会有点过分。任何多精度库都有巨大的开销。不仅需要大量开销,还需要巨大的开销。第二个想法是,您可能不需要使用多精度日志功能。也许你可以逃脱标准日志?

如果你不能在双精度浮点数中拟合你的计算,那么使用线程或其他方法进行并行化肯定会有所帮助。您可以尝试使用编译器优化,但我没有看到真正的改进尝试。

您可以尝试的最后一个选项是手动分配内存空间,以便MPFR具有固定的开销。我从未尝试过,所以我不知道它是否会有所帮助。