我需要在我的一些代码中使用对数函数,但底数并不重要。因此,如果我发现任何显着差异,我开始在 、 和 性能log()
之间log2()
进行选择。log10()
(我将把所说的函数分别称为ln
、lb
和lg
)。
我为什么要为此大惊小怪?因为我将在优化算法的每次迭代中调用该函数多达 400,000,000 次。这既不是可选的,也不是我问题的主题。
我设置了一些非常基本的测试,如下所示:
timespec start, end;
double sum = 0, m;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &start);
for (int n = 1; n < INT_MAX; ++n)
{
m = n * 10.1;
sum += log(m);
}
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &end);
cout << "ln=";
cout << diff(start, end).tv_sec << ":" << diff(start, end).tv_nsec << endl;
... // likewise for log2 and log10
(timespec diff(timespec start, timespec end)如果您愿意的话....)
获得了以下结果:
GCC v4.6.3
-O0
ln=140:516853107
lb=155:878100147
lg=173:534086352
-O1
ln=133:948317112
lb=144:78885393
lg=163:870021712
-O2
ln=9:108117039
lb=9:134447209
lg=4:87951676
-O3
ln=9:102016996
lb=9:204672042
lg=4:153153558
我已经查看了 compile 的输出-S
,但我对汇编程序的掌握还不够好,无法完全理解这些差异。-S
输出:-O0 -S , -O3 -S
为什么lg
使用 O2/O3 可以更好地优化?
编辑:源代码,注意第三个循环中的错字,这是 log10 看起来更快的原因(多。得到优化)。我已经接受了我认为最接近的答案,因为这个问题现在已经结束,尽管我从 drhirsch 和 janneb 的答案中学到了很多东西。