2008年 3月 11日 火曜日 Sun Studio 12, cc で SIMD 命令の使用を指定する (自動ベクトル化)
以前のエントリで、姫野ベンチを色々なコンパイルオプションを使ってコンパイル/実行してみました。そこで実行した中で一番成績が良かったのは以下のオプションでした。このエントリでは以下のオプションの中の -xvector=simd について見ていきたいと思います。
-DMIDDLE -fast -m64 -xvector=simd -xprofile=use:bmt
-xvector=simd
この指定によって SIMD 命令の生成が行われます。gcc 等で「自動ベクトル化」と説明される機能と同等で、ループを解析して可能であれば SIMD 命令を使ってベクトル演算をするようにコンパイルします。2007 年 11 月の Sun Tech Days 東京での Sun Studio のセッションでは以下のように、左のループが右のループに変換される例が説明されていました:
for (i=0; i<1024; i++) for (i=0; i<1024; i+=4) c[i] = a[i] * b[i] =====> c[i:i+3] = a[i:i+3] * b[i:i+3]
この例で説明しているのは、SIMD 命令が 1 回の実行で 4 つのデータを同時に取り扱うことができるという前提で、左のループでループ 4 回分に相当する処理が右のループでは 1 回で済み、その結果ループの回数 (命令の実行回数) が削減され、実行速度の向上が見込まれる。というものです。
「SIMD 命令によって、左のループで 4 回分に相当する処理が右のループでは 1 回で済む」という部分を具体的に見てみるために、手元の姫野ベンチをコンパイルして、Sun Studio 12 のアナライザ analyzer(1) でアセンブラを見てみたところ、C ソースの 215 行目の積を演算する部分で以下のコードが現れていました
... [215] 80552bf: movlps 0x1050804(%esi),%xmm1 [215] 80552c6: movhps 0x105080c(%esi),%xmm1 [215] 80552cd: movlps 0x408(%ebx),%xmm6 [215] 80552d4: movhps 0x410(%ebx),%xmm6 [215] 80552db: mulps %xmm6,%xmm1 ...
movlps、movhps はインテルのデベロッパーズガイドでそれぞれ以下のように説明されていました
上記の 80552bf, 80552c6 で xmm1 に、80552cd, 80552d4 で xmm6 にそれぞれ 4 つの単精度浮動小数点値が用意されて、80552db で mulps によって 4 つの積が一度に求められています。コンパイルされたすべてのアセンブラを読んで理解できたわけではないので、ピンポイントで「これがそうかな?」と理解しているに過ぎませんが、局所的には確かに:
「1 回の積の演算で 4 つのデータが処理されている」
ということになります。これによるパフォーマンスの向上が今回の計測結果で現れたようです。-xvector=simd オプションの有無で比較すると約 2 - 4 % の向上です。わずかな向上ではありますが、元のコードにまったく手を加えることなく試みることができるパフォーマンス向上のための手段と言うことで、検討する価値はあるように思えます。
-xvector=simd を指定しないでコンパイルした場合には、同じ行は mulss (Multiply Scalar Single-Precision Floating-Point Values) によって積が求められていたので、-xvector=simd の有無で明らかに演算方法は異なっていました。
-xvector=simd を使用する際には -xdepend を同時に指定してループの分析を行う必要がありますが、-xdepend を指定せずに -xvector=simd を指定した場合にはコンパイラが自動で -xdepend を指定してコンパイルを実行します。
Sun Tech Days 東京のセッションでは、-xautopar による自動並列化よりは効果は少ないと説明されていました「SPECfp 2006 で 3% の向上、個々の部分で 1 - 7 % 程度の向上」。-xautopar による自動並列化については別の機会に見てみたいと思います。
参考:
Posted by keiichio
( 3月 11日 2008年, 11:23:58 午前 JST )
Permalink
投稿されたコメント [0]