gccのコンパイルオプションでのarch指定
gccのコンパイル時に指定する動作CPUについての指定があるけど、あれってどの程度意味があるのかと思いちょっと調べる。
ターゲットプラットフォームはCore2DuoのMacBook。この世代のプロセッサに対しては直接対応するモデルが無いので、どれが一番効くのかな、とか。
ベンチマークに使ったのはN-Queen問題の解法プログラム。これを選んだ理由は特になし。gccはMacOS X標準のgcc-4.0.1。全ての結果は5回実行したときの単純平均。
まずは最適化オプションから。
コンパイルオプション | n=17のときの計算時間 |
-O0 -m32 | 163.842 |
-O1 -m32 | 85.884 |
-O2 -m32 | 81.75 |
-O3 -m32 | 78.08 |
-Os -m32 | 76.986 |
まぁ、順当に速くなる。ただ、解法プログラムのコアとなるアルゴリズムは一つの関数で完結しているので、O2からO3へ変えたときに関数のインライン展開が効いて速くなるのはやや解せない。サイズ重視の最適化をしたときの方がO3より速くなっているのも謎。
次はmarchやmtuneでCPUを指定したとき。
コンパイルオプション | n=17のときの計算時間 |
-O3 -mtune=i386 -m32 | 85.34 |
-O3 -march=i386 -m32 | 78.774 |
-O3 -mtune=i586 -m32 | 77.506 |
-O3 -march=i586 -m32 | 77.51 |
-O3 -mtune=i686 -m32 | 83.706 |
-O3 -march=i686 -m32 | 83.706 |
-O3 -mtune=pentium4 -m32 | 81.326 |
-O3 -march=pentium4 -m32 | 81.32 |
-O3 -mtune=prescott -m32 | 78.094 |
-O3 -march=prescott -m32 | 78.09 |
なんともはや、結果は出たり凹んだりと微妙なバラつき具合。やはり問題が小さすぎるのか明確な傾向が出てくれない。
アセンブラのソースを吐かせて眺めた感じだとmtuneのときにはプログラムの流れを変えるような変更はされなくて、細かい順序の入れ替えや命令の好き嫌いに応じた変更が中心。それに対して、marchの場合だとやや積極的に最適化が行われる。特にi686以降ではcmov関連の命令が使えるようになるため、そちらが積極的に使われる。これによってアセンブラ中でのラベル数が減っており、フロー的にも分岐が減っているようだ。これらの効果はもうちょっと複雑な問題を解かせたり、複数のベンチマークを総合しないと明確には出てこないのかもしれない。
お次は64bitのとき
コンパイルオプション | n=17のときの計算時間 |
-O0 -m64 | 160.174 |
-O1 -m64 | 71.796 |
-O2 -m64 | 70.224 |
-O3 -m64 | 70.99 |
-O3 -mtune=nocona -m64 | 71.044 |
-O2 -march=nocona -m64 | 70.258 |
-O3 -march=nocona -m64 | 70.962 |
流石に速い。Core2Duoが出たての頃は64bitコードが遅いとか言われていたが、なかなかどうして1割ぐらい速くなった。
ちなみに、この程度のプログラムでもちゃんと拡張されたレジスタを使うコードが吐かれていた。追加されたレジスタも32bitや16bit単位でアクセスできるし64bitにするペナルティはほとんど無いのかも。
もうちょっとちゃんと測るには、キャッシュに入り切らないような問題を選ばなければだめか。