代码之家  ›  专栏  ›  技术社区  ›  Kyle Simek

C++Exp与Log:哪个更快?

  •  12
  • Kyle Simek  · 技术社区  · 16 年前

    double log_num_1 = log(1.23);
    double num_2 = 1.24;
    

    num_1 num_2 ,我必须使用其中之一 log() exp() cmath 图书馆。

    换句话说,以下内容在语义上是等价的,所以哪个更快:

    if(exp(log_num_1) > num_2)) cout << "num_1 is greater";
    

    if(log_num_1 > log(num_2)) cout << "num_1 is greater";
    
    8 回复  |  直到 16 年前
        1
  •  22
  •   peterchen    16 年前

    就算法而言,复杂性是相同的,差异应该只是一个常数(希望可以忽略不计)。 因此,我会使用 exp(a) > b ,仅仅是因为它不会在无效输入时中断。

        2
  •  8
  •   Emil H    16 年前

    真的 需要知道吗?这会占用你大部分的跑步时间吗?你怎么知道?

    更糟糕的是,它可能依赖于平台。然后呢?

    当然,如果你在乎的话,可以测试一下,但花很多时间在微观优化上通常是个坏主意。

        3
  •  6
  •   dmckee --- ex-moderator kitten    16 年前

    编辑:修改代码以避免exp()溢出。这导致这两个功能之间的差距大幅缩小。谢谢你,弗雷德里克。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main(int argc, char **argv)
    {
        if (argc != 3) {
            return 0;
        }
    
        int type = atoi(argv[1]);
        int count = atoi(argv[2]);
    
        double (*func)(double) = type == 1 ? exp : log;
    
        int i;
        for (i = 0; i < count; i++) {
            func(i%100);
        }
    
        return 0;
    }
    

    (编译使用:)

    emil@lanfear /home/emil/dev $ gcc -o test_log test_log.c -lm
    

    结果似乎相当确凿:

    emil@lanfear /home/emil/dev $ time ./test_log 0 10000000
    
    real    0m2.307s
    user    0m2.040s
    sys     0m0.000s
    
    emil@lanfear /home/emil/dev $ time ./test_log 1 10000000
    
    real    0m2.639s
    user    0m2.632s
    sys     0m0.004s
    

    有点令人惊讶的是,log似乎更快。

    纯粹的猜测:

    taylor series 对数收敛得更快还是什么?在我看来,它实际上就像 natural logarithm 比计算更容易 exponential function :

    ln(1+x) = x - x^2/2 + x^3/3 ...
    e^x = 1 + x + x^2/2! + x^3/3! + x^4/4! ...
    

        4
  •  5
  •   ackb    16 年前

    因为你是在用价值观工作<<1,注意x-1>x的log(x)<1. 这意味着x-1<log(y)意味着log(x)<log(y),已经 无需使用log或exp即可处理1/e~37%的病例。

        5
  •  3
  •   cobbal    16 年前

    python中的一些快速测试(使用c进行数学):

    $ time python -c "from math import log, exp;[exp(100) for i in xrange(1000000)]"
    
    real    0m0.590s
    user    0m0.520s
    sys     0m0.042s
    
    $ time python -c "from math import log, exp;[log(100) for i in xrange(1000000)]"
    
    real    0m0.685s
    user    0m0.558s
    sys     0m0.044s
    

    编辑:C函数似乎被编译器优化了,所以循环占用了时间

    有趣的是,在C中,它们的速度似乎是一样的(可能是因为马克在评论中提到的原因)

    #include <math.h>
    
    void runExp(int n) {
        int i;
        for (i=0; i<n; i++) {
            exp(100);
        }
    }
    
    void runLog(int n) {
        int i;
        for (i=0; i<n; i++) {
            log(100);
        }
    }
    
    int main(int argc, char **argv) {
        if (argc <= 1) {
            return 0;
        }
        if (argv[1][0] == 'e') {
            runExp(1000000000);
        } else if (argv[1][0] == 'l') {
            runLog(1000000000);
        }
        return 0;
    }
    

    给出时间:

    $ time ./exp l
    
    real     0m2.987s
    user     0m2.940s
    sys      0m0.015s
    
    $ time ./exp e 
    
    real     0m2.988s
    user     0m2.942s
    sys      0m0.012s
    
        6
  •  1
  •   Mark    16 年前

    它可能取决于你的libm、平台和处理器。你最好写一些调用 exp / log 大量使用 time 打几次电话,看看是否有明显的区别。

    两者在我的电脑(Windows)上花费的时间基本相同,所以我会使用 经验 ,因为它是为所有值定义的(假设您检查 ERANGE ).但如果使用起来更自然 日志 ,你应该使用它,而不是在没有充分理由的情况下试图优化。

        7
  •  1
  •   ParoXoN    16 年前

    原木速度更快是有道理的。..Exp必须执行多次乘法才能得到答案,而log只需要将尾数和指数从2进制转换为e进制。

    如果您使用的是日志,请务必进行边界检查(正如许多其他人所说)。

        8
  •  0
  •   Alexey Orlov    16 年前

    如果你确定这是热点——编译器instrinsics是你的朋友。虽然它依赖于平台(如果你在这样的地方追求性能——你不能与平台无关) 所以,真正的问题是——哪一个是目标架构上的asm指令——以及延迟+周期。没有这一点,这纯粹是猜测。