MPI+ULT

MPI+ULTモデルの性能向上

現在のスパコンはノードの集合から構成されています。また、ノードは複数のCPUから構成されていてそれぞれがコアという計算資源を複数持っています。MPI+ULTモデルとはスパコンのノード間とノード内の並列を効率的に行うことができるプログラミングモデルの一つです。

まずはノード間の並列について説明します。並列計算をする上では入力データや計算結果の共有を行うために通信を行う必要があります。ノード間ではメモリは共有されていないため(分散メモリ)、明示的にデータの受け渡しを行わなくてはなりません。そこで使われるインターフェースとなるのがMPI(Message Passing Interface)というものです。

MPIはCまたはFortranプログラムから呼び出し可能な関数群から構成されています。例えば、ノード0からノード1にデータを送信したい時にはノード0がMPI_Sendという関数を、ノード1がMPI_Recvという関数を呼び出すことになります。その際に、通信先のノードを引数に指定します。今回の例だとMPI_Sendの引数の送信先のノードの番号に1を、MPI_Recvの引数の受信元のノードの番号に0を指定します。どちらの関数も呼び出したら通信が終了するまでブロックします。

次にノード内の並列について説明します。ノード間と違ってノード内ではメモリが共有されています。メモリを共有できる処理の分割の単位をスレッドと呼びます。ノード内並列は、ノード内で複数のスレッドを生成して計算を行い、通信は共有メモリを用いて行うことで実現されます。 スレッドといっても様々な実装がありますが、最も有名なものがOSの提供するスレッドで、POSIXにおいてはPthreadsというライブラリとして知られています。一方、OSの提供するスレッド上で実装されたスレッドもあり、ULT(ユーザーレベルスレッド)と呼ばれています。ULTはOSの提供するスレッドと比較してスレッド同士の切り替え(コンテクストスイッチ)が2桁ほど高速に行えることが特徴です。田浦研究室で実装されたMassiveThreadsもULTライブラリの1つです。

ノード間並列にMPIを、ノード内並列にULTを用いるモデルがはじめに述べたMPI+ULTモデルです。しかし、性能の良いMPI+ULTモデルの実装は現状存在しません。その大きな原因は、MPIをマルチスレッドで呼び出すためにはMPI内部で複雑で重い排他制御をする必要があるためです。したがって、今までノード間ノード内並列はMPIのマルチスレッド呼び出しを避けるために、通信と計算のフェイズを分離するという手段で実現されてきました。つまり、ノード間並列において、計算のフェイズはマルチスレッドで行い、通信のフェイズはシングルスレッドで行うというものです。しかしこのモデルはプログラマに大きな負担がかかります。具体的には、同じ時間で全てのノード内の通信資源が計算を終わるようにチューニングを繰り返さなくてはならないことや、通信と計算のオーバーラップをプログラマが指示しなくてはならないことなどです。

性能とプログラミングの容易さを兼ね備えたプログラミングモデルとして、田浦研究室ではMPI+ULTモデルを有望なモデルと考え、その性能向上の研究を行なっています。

https://i.imgur.com/U07eJtE.png