Netlib/vector ベンチマークによる自動ベクトル化機能の検証 山口 倉平, 池田 健二, 疋田 淳一 京都大学 情報部 情報基盤課 [email protected] 概要:近年の x86 系プロセッサは、SSE/AVX/AVX2 等のベクトル演算を行う命令セットの追加によ る性能向上が行われてきており、プログラムの高速化には演算のベクトル化が非常に重要である。本 稿では、複数のコンパイラを用いて、コンパイラが有している自動ベクトル化機能の調査・検証を行 った結果について報告する。 1. はじめに 近年の Intel 社の Xeon に代表される x86 系プ の情報も出てきていることから、当面は同様な方 向での機能強化が行われると考えられる。 ロセッサ(以下、プロセッサと言う)の進化は、 マルチコア化、メニーコア化と並行して SSE や 3. 計算機環境とコンパイラ AVX 等のベクトル演算を行う命令セットの追加に 3.1. ハードウェアと OS 検証に使用したシステムは Cray 社製の XC30 であり、Intel Xeon E5-2695v3 2.3GHz(Haswell) を 2 基と 64GB のメモリを搭載するノードを専用 の高速ネットワークで 416 台結合した MPP シス テムである。OS は SUSE Linux をベースとして いる Cray Linux Environment である。今回の検 証では XC30 のうち 1 台を使用した。 よる性能向上が行われてきており、プログラムの 高速化には、演算のベクトル化が重要な要素とな っている。そこで、スーパーコンピュータ関連の ソフトウェア資産が集められている Netlib[1]サ イトで公開されている Vector ベンチマークにより、 京都大学学術情報メディアセンター(以下、セン ターと言う)のスーパーコンピュータに導入して いる 3 種類のコンパイラを用いて自動ベクトル化 機能の検証を行った。 本稿では、プロセッサの動向について概説し、 検証に用いた計算機およびソフトウェア環境につ いて紹介した後、Netlib/Vector ベンチマークを 用いた検証結果について報告する。 3.2. Fortran コンパイラ 検証に使用した Fortran コンパイラのベンダー、 バージョンについて、表 1 に示す。いずれも自 動ベクトル化機能を有し、Xeon E5-2695 で利用 可能な AVX2 命令に対応している。 2. プロセッサの動向 Intel 社 が Pentium プ ロ セ ッ サ 時 代 に MMX/SSE といった SIMD(Single Instruction Multiple Data)型の命令セットを搭載し、その後 も強化が進められてきた中、2011 年に登場した SandyBridge 世代のアーキテクチャにおいては新 たな命令セットとして AVX(Advanced Vector eXtensions)が追加された。ビット幅もそれまで の 128 ビットから 256 ビットに拡張され、2013 年に発表された Haswell 世代では、さらに機能拡 張した AVX2 が搭載されている。また、Xeon Phi と呼ばれるメニーコアのコプロセッサでは、512 ビット幅の SIMD 命令に対応しており、次世代で は AVX-512 といったさらなる命令セットの拡張 表 1 コンパイラ ベンダー バージョン(-V オプションより) CRAY Cray Fortran 8.3.0 Intel Intel Compiler XE 14.0.3.174 PGI PGI Compilers 14.9-0 3.3. 自動ベクトル化 自動ベクトル化とは、コンパイラがプログラム のループ処理を対象に、ベクトル化による処理が 可能な場合には SIMD 命令により処理を行うコー ドを生成する機能のことである。手作業でプログ ラムを新たに追加、修正しなくても容易に実行性 能を向上することが可能となる。現在使われてい るコンパイラの多くに自動ベクトル化機能が備わ っているが、コンパイラの実装状況によってベク トル化の対象とできるループが異なる。 4. 自動ベクトル化機能の検証 4.1. Netlib/Vector ベンチマーク Netlib/Vector ベンチマークは、ベクトル計算 機のためのベクトル化機能を評価するためのテス トスィートとして開発されたものである。プログ ラムは、Fortran77 でコーディングされており、 ベンチマークのためのドライバルーチン群から構 成される maind.f とベクトル化機能の評価のため に集められた 135 種類のループを含む loopd.f の 二つのファイルで構成される。Vector ベンチマー クは、コンパイルリストやメッセージからだけの ベクトル機能の評価だけではなく、ループ長(配 列サイズ)10,100,1000 での実行結果および性 能も検証することができる。 表 2 コンパイルオプション Vender Options CRAY -hpic -O3 –h msgs -ra Intel -O3 -xCORE-AVX2 -ipo -no-prec-div -vec-report3 -opt-report1 -mcmodel=medium -shared-intel PGI -O4 -fastsse -tp haswell -Mvec=simd:256 -Minfo=all -mcmodel=medium 4.3.1. Cray コンパイラ ベクトル化のオプションはデフォルトで有効な ため、最適化のオプションとしては -O3 のみを 指定した。最適化情報を表示するためのオプショ ンとして-h msgs、-ra を指定した。ベクトル化し た際には、次のメッセージが表示される。 ftn-6204 ftn: VECTOR File = loopd.f, Line = 200 4.2. ベンチマークの拡張と修正 1)ループ長の拡張 自動ベクトル化の効果を測定するには十分なル ープ長も必要となるため、配列サイズを 10,000 にも対応させる拡張を行った。 2)計時ルーチンの修正 Vector ベンチマークは CPU 時間の計測処理が 組み込まれているが、自動ベクトル化の効果を計 測するために gettimeofday ルーチンを使って経 過時間を計時するよう修正した。 4.3. コンパイルオプション 各コンパイラのベクトル化機能検証のために、 Vector ベンチマークの loopd.f に対しては、各コ ンパイラのベクトル化、並列化、最適化オプショ ンおよび並列化ループを割出すためのコンパイル リスト、メッセージ出力のためのオプションを指 定した。一方 maind.f については、高度な最適化 の副作用を避けるために一部の最適化を抑止した。 loopd.f コンパイル時のオプションを表 2 に示す。 A loop starting at line 200 was vectorized. 4.3.2. Intel コンパイラ ベクトル化のオプションは、-xCORE-AVX2 を 指定し、最適化オプションは -fast と同等なオプ ションである -O3、-ipo、-no-prec-div を指定し た。maind.f のコンパイル時のみ、プログラムソ ース間の最適化による副作用を避けるために、 -ipo ではなく -no-ipo を指定した。ベクトル化お よび最適化のレポート生成のために、 -vec-report3 および-opt-report1 を指定した。ベ クトル化した際には、次のメッセージが表示され る。 loopd.f(3917): (col. 16) remark: LOOP WAS VECTORIZED 4.3.3. PGI コンパイラ ベ ク ト ル 化 の オ プ シ ョ ン は 、 -fastsse -tp haswell -Mvect=simd:256 を指定し、最適化オプ ションは-O4 を指定した。コンパイル時のベクト ル化および最適化情報のレポートを得るために -Minfo を指定した。ベクトル化した際には、次の メッセージが表示される。 s125: Generated vector sse code for the loop 4.4. ベクトル化されたループ数と実行時間 loopd.f に含まれる 135 種類のループを表 2 に 示すオプションでコンパイルした結果、ベクトル 化の対象となったループ数を表 3 に示す。ベクト ル化の有無の判断は、コンパイル時のメッセージ やコンパイルリストから目視で確認を行った。 Cray コンパイラが最も多い 89 種であり、Cray コンパイラのみがベクトル化できたループ数は 17 種、Intel コンパイラのみがベクトル化したル ープは 10 種、PGI コンパイラのみがベクトル化 したループは 1 種であった。 表 3 ベクトル化されたループ数 CRAY Intel PGI ベクトル化ループ数 89 86 64 対象外のループ数 46 49 71 次に、ベンチマークのループ長 10,000 におけ る全ループの実行時間の合計と、ループごとに各 コンパイラがベストタイム、ワーストタイムとな ったループ数を集計した結果を表 4 に示す。ベス トタイムのループ数の多さ、およびワーストタイ ムのループ数の少なさにおいてはクレイコンパイ ラが優れていたが、Intel コンパイラが全体の実行 速度では最速の 43.86 秒となり、CRAY コンパイ ラとは約 9 秒の差が開いた結果となった。 表 4 実行時間 CRAY Intel PGI 54.97 43.86 59.32 ベストタイムのループ数 67 52 16 ワーストタイムのループ数 35 40 60 実行時間合計[秒] 4.5. CRAY コンパイラが優位なケース CRAY コンパイラのみが自動ベクトル化してお り、かつ速度的に優れているループについて紹介 する。 配列のインデックス計算のあるループ !! s171 do 10 i = 1,n a(i*inc) = a(i*inc) + b(i) 10 continue ! cray: 0.033838 sec ! intel: 0.068522 sec ! pgi: 0.052126 sec 上記に示すのは、ベクトル化の対象となったル ープおよび各コンパイラにおけるループの実行時 間である。ループ s171 は、配列 a の添字に計算 式が含まれており、Intel コンパイラと PGI コン パイラは、データ依存があるとメッセージが出力 され、ベクトル化の対象外と扱われている。CRAY コンパイラはベクトル化可能と判断し、3 種のな かで最も速度的に優れた結果となっている。 ループの step が外部定義のループ !! s172, n3=1 (引数渡し) do 10 i = n1,n,n3 a(i) = a(i) + b(i) 10 continue ! cray: 0.033852 sec ! intel: 0.052843 sec ! pgi: 0.051074 sec ループ s172 のステップは変数 n3 で与えられて おり、この変数はこのループのサブルーチンの外 部で定義されている。Intel コンパイラはベクトル 化しても非効率である判定し、PGI コンパイラは データの依存性を読み切れないことで、ベクトル 化が行われていない。 依存関係がある演算を含むループ !! s241 do 10 i = 1,n-1 a(i) = b(i) * c(i) * d(i) b(i) = a(i) * a(i+1) * d(i) 10 continue ! cray: 0.093169 sec ! intel: 0.128660 sec ! pgi: 0.124503 sec ループ s241 は、a(i)と a(i+1)の演算順序がベク トル化に影響するが、CRAY コンパイラは式の変 換により、ベクトル化を行っている。Intel コン パイラと PGI コンパイラはデータの依存性により 対象外となっている。 複雑な if-goto ループ !! s412 10 continue i = i + inc if(i .gt. n)goto 20 a(i) = a(i) + b(i) * c(i) goto 10 20 continue ! cray: 0.046663 sec ! intel: 0.071322 sec ! pgi: 0.072364 sec ルー プ s412 は 、 goto 文 による ループ を if+goto によって break するものである。Intel コンパイラはデータの依存性を読み切れずにベ クトル化はできないと判断しており、PGI コン パイラはベクトル化の対象と認識していない。 4.6. Intel コンパイラが優位なケース 次に、Intel コンパイラのみが自動ベクトル化 しており、かつ速度的に優れているループについ て紹介する。 一次従属性のあるループ !! s116 do 10 i = 1,n-5,5 a(i) = a(i+1) * a(i) a(i+1) = a(i+2) * a(i+1) a(i+2) = a(i+3) * a(i+2) a(i+3) = a(i+4) * a(i+3) a(i+4) = a(i+5) * a(i+4) 10 continue ! cray: 0.230008 sec ! intel: 0.138010 sec ! pgi: 0.183665 sec ループ s116 は、ハンドコードでループアンロ ーリングされており、かつ演算に依存関係がある ループである。CRAY コンパイラはベクトル化可 能だが非効率と判断し、PGI コンパイラはデータ の依存性のため対象外としている。 4.7. PGI のみベクトル化したケース 次に、PGI コンパイラのみが自動ベクトル化し たループについて紹介する。 配列の添字を配列で指定するループ !! s4113 do 10 i = 1,n a(ip(i)) = b(ip(i)) + c(i) 10 continue !cray: 0.092281 sec !intel: 0.106195 sec !pgi: 0.102227 sec ループ s4113 は、配列の添字を未整列状態の配 列 ip で指定しているループであり、Cray コンパ イラと Intel コンパイラは非効率と判断している が、PGI コンパイラのみベクトル化している。PGI コンパイラの実行速度に特に優位な結果は見られ ない。ベクトル化できたループ数で他に差をつけ られている点からも PGI コンパイラの自動ベクト ル化は今後の強化が望まれる。 5. まとめ Netlib/Vector ベンチマークを使って最新の Xeon プロセッサ(Haswell)を対象に 3 種のコンパ イラにより、自動ベクトル化機能と実行性能につ いて検証し、各コンパイラの現状を知ることがで きた。アプリケーションの高速化には、MPI や ループ順序入替により非依存となるケース !! s233 loop interchange do 10 i = 2,n do 20 j = 2,n aa(i,j) = aa(i,j-1) + cc(i,j) 20 continue do 30 j = 2,n bb(i,j) = bb(i-1,j) + cc(i,j) 30 continue 10 continue !cray: 8.755476 sec !intel: 0.288408 sec !pgi: 8.606355 sec ループ s233 は、ループの入れ替えによってベ クトル化が可能となるコードであり、Intel コンパ イラのみがベクトル化の対象としている。実行性 能については、ベクトル化した Intel コンパイラ が圧倒的に高速な結果となっている。 OpenMP による並列化に加え、ベクトル化が重要 な要素であることから、コンパイラによる自動ベ クトル化は重要な機能であり、より一層の強化を 期待している。センターのスパコン導入ベンダー に対して測定したデータを提供し、機能向上に役 立てる事も考えている。今回の検証は、過去に Netlib で公開された Fortran77 に基づく評価とな ったが、Fortran90 以降の言語体系における検証 についても検討してみたいと考えている。 参考文献 [1] Netlib : http://www.netlib.org/benchmark [2] クレイ・ジャパン・インク : Cray Fortran Reference Manual [3] イ ン テ ル 株 式 会 社 : User and Reference Guide for the Intel® Fortran Compiler [4] NVIDIA Corporation : PGI Compiler Users Guide
© Copyright 2024 Paperzz