1
0

More than 3 years have passed since last update.

Devtoolset環境で-O2より-O3のが遅い

Posted at

概要

CentOS + devtoolset + Intel C++環境では、-O2オプションよりも-O3オプションを付けた方が計算速度が遅くなる場合がある(devtoolsetを自前コンパイルした場合は回避できるかも)。

原因はデフォルトでリンクされるlibstdc++がOS標準のものであるため。解決策としては、コンパイルオプションに-static-libstdc++を付けることでdevtoolset内のものがリンクされて計算速度も改善する。

環境

  • CPU:Intel Xeon Gold 6248 (Csacadelake)
  • OS: CentOS 7.8 (3.10.0-1127.19.1.el7.x86_64)
  • ライブラリ:devtoolset-9, Intel MPI
  • コンパイラ:Intel C++ (icpc 2021.2.0 20210228)

モチベーションと問題

科学技術計算の一つとしてMolecular Dynamics(MD)関連のC++コードをチューニングしていました1。AVX-512がバッチバチに効くようにするには、十分にinline展開されることが重要です。そこで、Intelコンパイラのオプションで-inline-factor=400などと指定して、inline展開の判断の上限を変えて計算速度の変化を見ておりました。

主なコンパイルオプションは次のようなものです。

mpiicpc -std=c++17 -O2 -ip -inline-factor=400 -no-prec-div -xCORE-AVX512 -qopt-zmm-usage=high

ちなみに、cppファイルは単一で、他はヘッダオンリーライブラリになっているので-ip-ipoに実質的な差は無いと考えています。

ここで、-inline-factorの数値以外にも、-O2の部分を-O3に変更して計算速度を比べました。時間測定はMPI_Wtime()関数を使いました。すると次のような結果になりました(具体的コードと計算対象は省略させてもらいますがご容赦ください)。

-inline-factorの数値 -O2の場合の計算時間[s] -O3の場合の計算時間[s]
100 (default) 33.992533 32.275774
200 33.077171 31.213558
300 28.193719 30.905700
400 28.431761 30.406196
500 28.878089 30.671972

この例ですと、inline-factor=300以上からinline展開されてAVXがより効きます。それ以下では一部のループがSIMD化されません。もちろん、inline展開を過度にするとバイナリサイズが大きくなり、キャッシュの問題と相まって遅くなると予想されます。

しかし、なぜかある時点から-O3オプションでコンパイルしたものが、-O2オプションでコンパイルしたものよりも遅くなっています。

解決策

なぜ遅くなるのか原因がわからず悩みました。

-O3にすることでバイナルサイズが増えたためか?しかし本当に微増しただけでした。

-O3でinline展開やSIMD化が変わったのか?しかし主要な計算部分では殆ど変化が無いように見えます。

以前に、std::chronoが遅いという記事2を書きました。そういえば今回の時間計測でstd::chronoを使ってしまっていないか疑ったものの、上述のようにMPI_Wtimeを使っております。その記事の調査からも、MPI_Wtime()libstdc++のリンクには寄らず高速であることがわかっています。今回のコードではstd::chronoはどこでもcallしていません。

しかし、その試行錯誤自体はビンゴで、結果的にコンパイルオプションに-static-libstdc++を付けると次のように-O3での速度が改善しました。

-inline-factorの数値 -O2 -static-libstdc++での計算時間[s] -O3 -static-libstdc++での計算時間[s]
100 (default) 35.054073 32.014642
200 34.101968 31.211953
300 28.266521 27.761617
400 27.664209 27.641717
500 28.185959 27.892363

どうやらstd::chrono以外にもOS標準のlibstdc++では速度の出ない関数があったのだと想像できます。もしくはリンク時インライン展開(-ipoではないけど多分)で問題になるところがあったのか。そこをdevtoolset付属のものにしたことで解決したのでしょう。

ただし-O2でinline展開が十分でない場合には速度が低下しているので注意は必要です。

では原因は何なのかという話になると断言できず。この込み入ったMPIのコードから一部分を切り出して原因となる関数を特定するのはとても困難で、現状諦めたい気持ちでいっぱいです。

おわりに

原因を完全には特定せず、中途半端なレポートで申し訳ないです。MPIでのベンチは本当に魔境で辛過ぎ。そもそもinline展開の上限を上げないとSIMD化できないような私のクソクラス設計に問題があるのは否めません。ですので、とてもレアなケースかもしれません。

また、gccclang(もしくはIntelのicpx)ならどうだという疑問もありそうですが、MPIのインストール状況などから今回は調査を断念します。

とりあえずdevtoolset環境で-O3を使う際は-static-libstdc++も併用してオプションに指定した方がよさそうです。誰かのお役に立てば幸いです。


  1. 正確にはMDのエンジンをコアに使ってMPMDでヘテロジニアスな計算を行うシミュレーションという特殊なものなので、一般論として今回の事例が良く起こるのかはちょっと自信がないです。 

  2. ある環境でstd::chronoが遅い 

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0