gccの自動ベクター化

これもgcc-4.0から入った機能。通常のループ処理を自動的にSSEなどを使った並列処理に展開してくれるという便利機能。ちょっとでもC言語を齧ったことがある人なら本当に動くのかなぁ、と疑いたくなる機能であるが、ちゃんと機能するなら非常に有用な機能だ。
使い方はコンパイル時のパラメータとして"-ftree-vectorize"というのを足してやるだけ。ただしこれではどのループが展開されたのかどうかわからないので、"-ftree-vectorizer-verbose=5"などとしてどれぐらい効いているかを報告させつつコンパイルするといいかも。
こういう機能が効きそうなコードとして、動画や音声を扱うx264とmplayerコンパイルしてみた*1
前者はコードのホットスポットとなる部分が手書きのアセンブラで書かれているので、これ以上最適化の余地がないためかベクター化されたのは3箇所のループだけ。いずれも初期化時に一回しか通らないようなしょぼいループなので、はっきり言って効果はほとんど無い。
後者は様々なフォーマットやコーデックに対応するためコード全体が大規模化していることもあってか、ベクター化できたのは172箇所。やはりスケーリングやフィルタなどの本当に効きそうな箇所はSSEがinlineで書かれてあるので対象とはならず、それ以外のループで最適化されたようだ。数カ所実際にベクター化に成功したループを見たが、ほとんどループ内が1行で完結するような簡単な処理。よくある初期時の1で埋めたり0で埋めたりしてあるような箇所は単純なため、しばしば対象となっていた。ループ内での処理が大きいときや、データの依存関係がある箇所はそれを機械的に判断して諦める。何故諦めたかも出力するので眺めていると結構面白い。
で、性能への効能の方はちゃんとデータが採れていなくてよくわからないというのが正直なところ。こんな小さなループ処理までインラインアセンブラで書いていたらキリがないだろうというところまで、最適化してくれるのは機械処理ならでは。実際には全体を通して性能向上への寄与がほとんど無いようなところを人間が脳味噌を使って書き直すのはマンパワーの無駄だ。
この処理を入れることによる悪影響が無いならば、ちょくちょく使っていきたい。

*1:ここのところ偏執的にgccで色々と試しているのは、これらバイナリを速く動かしたかったため