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

Kyl*_*mek 11 c++ math performance

我有一个C++应用程序,我需要比较两个值,并决定哪个更大.唯一的复杂因素是一个数字在日志空间中表示,另一个不在.例如:

double log_num_1 = log(1.23);
double num_2 = 1.24;
Run Code Online (Sandbox Code Playgroud)

如果我想比较num_1num_2,我可以选择使用log()或者exp(),我想知道如果有一个更容易计算比其他(即运行在更短的时间,一般).你可以假设我正在使用标准cmath库.

换句话说,以下是语义等价的,因此速度更快:

if(exp(log_num_1) > num_2)) cout << "num_1 is greater";
Run Code Online (Sandbox Code Playgroud)

要么

if(log_num_1 > log(num_2)) cout << "num_1 is greater";
Run Code Online (Sandbox Code Playgroud)

pet*_*hen 23

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

  • 关于log()更脆弱的非常好的观点.特别是因为性能差异在现实中可能不是问题. (3认同)
  • 感谢您的回答-非常有帮助。不过,我将使用 log(),因为我正在处理极小的正值(它们是概率),而且我认为在精度方面,我会过得更好。 (2认同)

Emi*_*l H 8

编辑:修改代码以避免exp()溢出.这导致两个功能之间的差距大大缩小.谢谢,fredrikj.

码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

(编译使用:)

emil@lanfear /home/emil/dev $ gcc -o test_log test_log.c -lm
Run Code Online (Sandbox Code Playgroud)

结果似乎相当有说服力:

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
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,日志似乎更快.

纯粹猜测:

或许基础数学泰勒系列会更快地收敛日志或什么?在我看来,自然对数指数函数更容易计算:

ln(1+x) = x - x^2/2 + x^3/3 ...
e^x = 1 + x + x^2/2! + x^3/3! + x^4/4! ...
Run Code Online (Sandbox Code Playgroud)

但是,不确定c库函数是否就是这样.但这似乎不太可能.

  • 不,指数函数的泰勒级数比自然对数的收敛速度快.但这可能无关紧要,因为数学库很可能使用极小极大多项式而不是泰勒多项式.exp的原因比测试中的log慢很多,可能是因为它大部分时间都会溢出,这需要处理.请注意,exp(i)已经在i = 700附近溢出.log不会溢出. (4认同)

dmc*_*kee 7

真的需要知道吗?这会占用你运行时间的很大一部分吗?你怎么知道的?

更糟糕的是,它可能取决于平台.那又怎样?

当然,如果你关心的话,测试一下,但花费大量时间在微优化上苦苦挣扎通常是一个坏主意.

  • 更糟糕的是,它可能取决于您运行的处理器(您的应用几乎肯定会比当前一代的CPU更长). (2认同)

ack*_*ckb 5

由于您使用值<< 1,请注意x-1> log(x)x <1,这意味着x-1 <log(y)表示log(x)<log(y),已经无需使用log或exp即可处理1/e~37%的案例.