EC2で 2TFlops 出してみた – HP Linpack on C5n –

2021.01.22

この記事は、AWS EC2上でHP Linpackを実行し浮動小数点演算性能を推定した際の「やってみた」記事です。

はじめに

そもそもLinpackとは?

Linpackとは、CPU性能を推定できる科学技術計算領域の演算ライブラリの1つです。 このプログラムは、理学・工学の様々な分野で広く用いられている解析シミュレーションプログラムの内部で使われている大規模な連立方程式を解くための行列演算に類する計算を行います。具体的にはBLAS等のライブラリを用いてn×n行列のLU分解を行い、その過程で実行したシステムの浮動小数点演算性能(Flops)が算出されます。 Wikipediaから引用させて頂きますと、以下の記述があります

主として線型代数の数値計算を目的とした、行列およびベクトルの演算が実装されているライブラリである。

HP Linpack (HPL) とは?

HPLは、複数ノードによる並列計算に対応したLinpackの実装で、スーパーコンピュータのランキングで有名なTOP500でも使われています。 実はCPUのベンチマークプログラムはLinpackだけではなく、他にも流体解析等でしばしば用いられる共益勾配法のプログラムであるHPCGなども近年話題となっております。

AWS EC2でコンピューティング性能を測定するために

AWS EC2ではGPUを除くとC4, C5等のインスタンスタイプがコンピューティング最適化インスタンスとして知られています。今回はその中でも複数ノードの並列計算を想定した十分なネットワーク性能が期待できるC5nインスタンスを選択しました。(ただし今回は複数ノードは使用せず、1ノード内のみのフラットMPI実行を実施しました。)

実はIntel® CPUを対象としたベンチマークの場合には、Intel®のMKL®と言う数値演算ライブラリを利用した方法が知られており、こちらを使うことで比較的手軽にIntel CPUの性能を引き出すことが可能になると思われます。
しかし今回はオープンな実装である以下の2つのライブラリを用いてHPLを実行する方法をご紹介します。

  • Open MPI
    • 並列計算のための通信規格Message Passing Interfaceの実装です。
  • OpenBLAS
    • 線形代数のサブプログラムであるBLASの洗練された実装です。

インスタンス作成時の注意点

まず、とても一般的なことですが、作業終了時に不要なAWSリソースの停止/終了を行ってください。
特に、C系インスタンスなど比較的単価の高いリソースを利用する際の消し忘れには、十分にご注意ください。

HP Linpack実施のためのAWS環境の構築に際しては、Parallel Cluster等を使用せず単純にVPCの中でEC2を動かすだけであれば、特別な設定は必要ありません。EC2の他にはSecurity GroupやInternet GateWayなどのリソースを用意できればOKです。

ただし、インスタンス作成時にCPUオプションを設定する必要がある点のみご注意ください。 コア別のスレッド数1に変更します。この点については公式ドキュメントの記載も併せてご確認ください。

EC2起動時の確認画面で、以下のようにvCPUが36と表示されることを確認します。

この設定は、物理サーバーにおけるIntel® CPUの一機能Intel® Hyper-Threading Technologyをオフにする設定に相当します。つまり、1プロセスから2スレッドではなく1スレッドのみを使えるように制限します。 HPCのワークロードでは一般的な設定で、解析時に必要な領域分割数(=スレッド数)を少なくすることができ、それによってMPI通信の不要なオーバーヘッドを抑制することができます。

ちなみにインスタンスが起動した後は、lscpuコマンドで以下のようにインスタンスのCPU情報を確認できます。

Architecture:                    x86_64  
CPU op-mode(s):                  32-bit, 64-bit  
Byte Order:                      Little Endian  
Address sizes:                   46 bits physical, 48 bits virtual  
CPU(s):                          36  
On-line CPU(s) list:             0-35  
Thread(s) per core:              1  
Core(s) per socket:              18  
Socket(s):                       2  
NUMA node(s):                    2  
Vendor ID:                       GenuineIntel  
CPU family:                      6  
Model:                           85  
Model name:                      Intel(R) Xeon(R) Platinum 8124M CPU @ 3.00GHz  
Stepping:                        4  

(snip)

準備

ライブラリのインストール

まずは、前述のOpenMPI、OpenBLASをインストールします。 詳しくはそれぞれのドキュメントに譲り割愛しますが、私はこれらライブラリのmakeを実施するためにOSは安易にUbuntu Server 20.04 LTSを選択し、コンパイルに必要なgcc、gfortran、g++、makeなどを簡単にapt-getで揃えられる環境で実施しました。

make installが完了したら、忘れずにライブラリのパスをbashrc等に追記してください。

$ echo 'export LD_LIBRARY_PATH=/usr/local/lib/openmpi:${LD_LIBRARY_PATH}' >> ~/.bashrc  
$ echo 'export LD_LIBRARY_PATH=/opt/OpenBLAS/lib/:${LD_LIBRARY_PATH}' >> ~/.bashrc

再度ログインし直し、念のためにmpirunのパスが通ってMPIが利用できる状態になっているかも確認します。

$ mpirun --version
mpirun (Open MPI) 4.1.0

HPLインストール

以下の手順でHPL最新版ver.2.3をダウンロードし展開します。

$ wget https://www.netlib.org/benchmark/hpl/hpl-2.3.tar.gz  
$ tar xvf hpl-2.3.tar.gz  
$ ls hpl-2.3  
$ mv hpl-2.3 hpl  # Makefileの仕様によりディレクトリ名を変更しておきます。
$ cd hpl

setupディレクトリ下のMakefileのいずれかをコピーして、Make.Linuxを作成します。(Makefile名のサフィックスは任意です。)
このファイルの必要な項目を修正します。MPIが問題なければ主にポイントは以下の部分と思われます。

Make.Linux

ARCH         = Linux

(snip)

LAdir        = /opt/OpenBLAS
LAinc        = -I${LAdir}/include
LAlib        = ${LAdir}/lib/libopenblas.a

コンパイルオプションは今回は特に変更していません。最適化オプションのO3が付いていますね。

Make.Linux

CC           = mpicc
CCNOOPT      = $(HPL_DEFS)
CCFLAGS      = $(HPL_DEFS) -fomit-frame-pointer -O3 -funroll-loops -W -Wall

最後にmakeを実行し、bin/Linuxディレクトリ下にバイナリが生成されていることを確認します。

make arch=Linux

HPLの実行

実行手順

HPLは実効バイナリと同じ場所に生成されたHPL.datを設定ファイルとして使用しています。
このHPL.datの中の主な入力パラメータは次のとおりです。 このパラメータの決定方法について詳しくないのですが、参考文献にあげたページやFAQをご参照いただき試行錯誤するのが良いと思われます。今回は時間も限られていたので適当に以下の値を選択しました。

Item Parameter
N 138564
NB 256
P 6
Q 6

PとQの乗数がプロセス数の合計値と一致していることを確認し、次のように実行します。

$ export OMP_NUM_THREADS=1
$ mpirun -np 36 ./xhpl

ここで設定しているOMP_NUM_THREADSはOpenMP(※OpenMPIではない)に関する環境変数です。

実行結果

正常に実行できると標準出力に以下のように表示されます。

-------------------------------------------------------------------------------- 
HPLinpack 2.3  --  High-Performance Linpack benchmark  --   December 2, 2018
Written by A. Petitet and R. Clint Whaley,  Innovative Computing Laboratory, UTK  
Modified by Piotr Luszczek, Innovative Computing Laboratory, UTK  
Modified by Julien Langou, University of Colorado Denver  
-------------------------------------------------------------------------------- 
An explanation of the input/output parameters follows:
T/V    : Wall time / encoded variant.
N      : The order of the coefficient matrix A.
NB     : The partitioning blocking factor.
P      : The number of process rows.
Q      : The number of process columns.
Time   : Time in seconds to solve the linear system.
Gflops : Rate of execution for solving the linear system.

The following parameter values will be used:

N      :  138564
NB     :     256
PMAP   : Row-major process mapping
P      :       6
Q      :       6
PFACT  :    Left    Crout    Right
NBMIN  :       2        4
NDIV   :       2
RFACT  :    Left    Crout    Right
BCAST  :   1ring
DEPTH  :       0
SWAP   : Mix (threshold = 64)
L1     : transposed form
U      : transposed form
EQUIL  : yes
ALIGN  : 8 double precision words  
--------------------------------------------------------------------------------  
- The matrix A is randomly generated for each test.
- The following scaled residual check will be computed:
||Ax-b||_oo / ( eps * ( || x ||_oo * || A ||_oo + || b ||_oo ) * N )
- The relative machine precision (eps) is taken to be               1.110223e-16
- Computational tests pass if scaled residuals are less than                16.0

T/V                N    NB     P     Q               Time                 Gflops

--------------------------------------------------------------------------------
WR00L2L2      138564   256     6     6             826.27             2.1466e+03
HPL_pdgesv() start time Thu Jan 21 21:05:54 2021

HPL_pdgesv() end time   Thu Jan 21 21:19:40 2021

--------------------------------------------------------------------------------
||Ax-b||_oo/(eps*(||A||_oo*||x||_oo+||b||_oo)*N)=   1.40250260e-03 ...... PASSED

2.1466e+03GFlopsという結果でした。PASSEDとなっておりresidualも問題無さそうです。

最後に、作業が完了したらEC2インスタンスを忘れずに停止してください。

改めてCPUについて

ここで改めて今回利用したC5nのスペックを確認すると以下のとおりです。

Instance c5n.18xlarge
vCPUs 36 cores (HT Off)
CPU Intel® Xeon® Platinum 8124M
Memory 192 GB
NW Bandwidth 100 Gbps
Virtualization HVM

このCPUがコードネームSkylakeでAVX-512 FMAユニット2基が搭載されているとすると、単純計算で理論性能は3.46TFlopsになり、見かけ上の実効効率は62%程になります。
(ここではフルコアでの実行という理由とHVM等仮想化技術との関連も考えられるためIntel® Turbo Boost Technologyについては触れていないのですが、本来であればある程度考慮すべきと思われます。)

おわりに

最後までご覧いただき、ありがとうございました。
実効効率は低く、まだまだSkylakeやOpenBLASの性能を引き出せていないのですが、今回は「やってみた」記事のため、もしまた機会があれば追加の検討をしたいと思います。
実際のところ、C5n上では2,3回しかxhplを実行していないため、入力ファイルのパラメータ変更だけでも改善する余地はありそうです。
専門的な領域の記事ですが、どなたかに届けば幸いです。

参考文献

以下のページを参考にさせていただきました。