複数GPUのスケーリング
複数GPUを使用して性能を上げる場合、GPU数に比例してサイズの大きな問題を同じ処理時間で解くWeak Scalingというやり方がある。
理想的なWeak Scalingではノード数(例えばGPU数)が変わっても処理時間は変わらない。
これに対して、問題のサイズは一定で、ノード数が増えると各ノードの処理量が減少するStrong Scalingというやり方がある。
理想的なStrong Scalingではノード数の逆数で解を得るまでの時間が短くなっていく。
MERGESORTの例
一例として、MERGESORTでは、前半はリスト全体を半分、半分というように次々に分割して行き、1要素になるまで分割する。そして、後半では、分割された2つのサブリストから1つの要素を取り出し、大小関係が正しくなるように併合する。これを繰り返して順に要素を大きくして行き、最後には値の大小の順が揃った1つのリストにする。
リストAとリストBは内部では正しい順序になっているとする。そして、AとBのリストを纏めて1つの正しい順序のリストを作る場合を考える。この時、AとBのリストの要素を順番に見て正しい順序になるように選んでいくのが一番分かりやすいが、これでは並列処理ができない。
ここで取り上げる方法は、リストAの全要素についてA[i]<B[j]となる最小のjを求め、A[i]を結果のリストDのD[i+j]に格納するというやり方である。このやり方であれば、リストAのすべての要素でそれぞれに対応するjのサーチを並列に実行することができる。
なお、最小のjを見つけるにはバイナリサーチを必要とする。
この図で並んでいる青い箱には、MERGEするリストAとリストBの要素が交互に入っている。そして、マージの最初のステップではAとBの1要素を2要素のリストにマージする。そのためにライトバッファへの書き込み場所を前述のアルゴリズムにしたがって計算する。そして、書き込みを行い、並列に動作しているカーネルを同期する。
そして、書き込んだバッファを次回の入力にして、不要になった入力バッファを次回の書き込みバッファにする。
2段目は2要素のリスト同士をソートして4要素にする。そして、3段目は4要素のリスト同士をソートして8要素にという風にして、最終的には1つのリストを作り上げる。
このMERGESORTでは2MBのGPUのページを使い、スレッドやデータのアライメントには特に気を使わなかった。しかし、1台のGPUには80SMあり、それぞれのSMで1024スレッドを動かしているので、16GPUでは1回のReadで10,485,760バイトを読んでおり、全体としてはほとんどメモリアクセス量の偏りは出ない。
次の図は、4個、8個、12個、16個のV100 GPUを使ってMERGESORTを行った場合の実際に達成できたメモリバンド幅を示すグラフである。横軸は、何個の要素のリストのソートを行ったかである。
16個のGPUを使った場合、最大で6TB/sを若干超える性能でメモリの読み書きが行なえている。
次の図は8Billion要素のソートを4~16GPUで行ったStrong Scalingの図である。3本の折れ線グラフは、一番上が効率、2番目のオレンジの線が実際の処理時間(秒)、一番下の青線が理想的なストロングスケーリングの処理時間である。この80%というスケーリング効率は非常に高いものである。
(次回は4月22日に掲載します)