コードの一部で対数関数を使用する必要がありますが、底は問題ではありません。そのため、大きな違いが見つかった場合は、パフォーマンスによって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
でコンパイルした出力を見てきましたが-S
、違いを完全に理解するのに十分なほどアセンブラを把握していません。-S
出力: -O0 -S、-O3 -S
lg
O2/O3 での最適化が優れているのはなぜですか?
編集:ソース コード、3 番目のループのタイプミスに注意してください。drhirsch と janneb の回答から多くのことを学びましたが、質問が閉じられたため、最も近いと思われる回答を受け入れました。