資料 - 大学ICT推進協議会

Netlib/vector ベンチマークによる自動ベクトル化機能の検証
山口 倉平, 池田 健二, 疋田 淳一
京都大学 情報部 情報基盤課
computing@media.kyoto-u.ac.jp
概要:近年の 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