NOTE
この記事は最終更新日から1年以上が経過しています。内容が古くなっている可能性があります。
今日はコンパイルの最適化オプションが単純なループと整数演算をどのくらい高速化できるかを見てみます。
サンプルプログラムをCで書きました。1からコマンド引数に渡した値まで順番に足し合わせるtest.cです。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
long long unsigned int i=0, j=0, a=atoll(argv[1]);
while (i<a)
j += ++i;
printf("%llu\n", j);
return 0;
}環境は Ubuntu 12.04 の gcc version 4.6.3 を使います。
$ gcc -v
...
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)まずは、普通にコンパイルして実行します。
$ gcc test.c
$ time ./a.out 9876543210
11879564747017720423
real 0m21.469s
user 0m21.469s
sys 0m0.000s1から9876543210まで足し合わせるのに21秒かかりました。さて、最適化オプションを試してみましょう。ちなみに -O2 で有効になっているオプションを見るにはこんな感じでコマンドを打ちます。
$ gcc -c -Q -O2 --help=optimizers | grep enabled
-falign-functions [enabled]
-falign-jumps [enabled]
-falign-labels [enabled]
-falign-loops [enabled]
-fasynchronous-unwind-tables [enabled]
-fbranch-count-reg [enabled]
-fcaller-saves [enabled]
-fcombine-stack-adjustments [enabled]
...うーん。なんとなく何をしてくれるかわかるのもあれば、よくわからないのもあります。ちゃんと知りたいときはmanを読めばいいんじゃないかな。とりあえず実行速度がどうなるのか知りたいだけなので -O2 を指定して実行してみましょう。
$ gcc test.c -O2
$ time ./a.out 9876543210
11879564747017720423
real 0m2.755s
user 0m2.748s
sys 0m0.004sおぉ、速くなった、速くなった。どんな理屈で速くなってるかは謎ですが、ちゃんと9876543210サイクルの計算をしてる気もします。詳しく調べてみると面白そう。せっかくだから Mac OS X Mavericks でもやってみましょう。
$ gcc test.c -O
$ time ./a.out 9876543210
11879564747017720423
real 0m0.005s
user 0m0.001s
sys 0m0.002sなにこれ速すぎ。 Mavericks の xcode に入ってるコンパイラは、「これって等差数列の和を計算してるんだから、ループなんて必要ないじゃん」てことを解析してるっぽい。このコンパイラのバージョンはを見てみると、
$ gcc -v
...
Apple LLVM version 5.0 (clang-500.2.79) ...これ gcc やない、LLVM clang や。どうやら Mac OS X Mavericks の gcc コマンドの中身は LLVM clang みたいです。 LLVM かしこい。