5

我正在编写一个用于统计抽样的小型库,它需要尽可能快地运行。在分析中,我发现函数中大约 40% 的时间用于计算斯特林对阶乘对数的近似值。我将我的优化工作集中在这部分上。这是我的代码(使用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 个输入。
  • 优化数学(使用更粗略的近似以获得更小的精度)
  • 使用多个线程并行计算不同的输入
  • 当数字可以适合机器数据类型时切换到本机算术

我可以采取其他方法吗?

4

2 回答 2

2

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

那将是我的第一次尝试。MPFR 可能会成为性能杀手。

在我看来,您想计算 n 的对数!您已经用斯特林公式进行了近似。

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

只有当上述所有方法在性能方面都失败时,我才会推出我自己的粗略近似值。

于 2014-02-12T17:23:07.447 回答
1

这里有几个想法。首先,在我看来,为此使用 MPFR 可能是矫枉过正。任何多精度库都有巨大的开销。不仅开销很大,而且开销很大。第二个想法是,也许您不需要使用多精度日志功能。也许您可以摆脱标准日志?

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

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

于 2014-02-12T17:14:49.420 回答