METISで領域分割する

概要

  • 非構造MPI並列セル中心有限体積法コード用のメモです。
  • MPIなどで空間を並列処理する際の分割をMETISで半自動化します。
  • METISのコマンドを手動実行します。実行環境に縛られにくい利点があります。
  • Ubuntuで動かしていますがgpmetisコマンドが使えれば何でも良いです。

準備

  • METISのコマンドが使えるようにインストールします。
    • sudo apt update
    • sudo apt install  metis -y
    • 端末で"gpmetis"を実行してコマンドが認識されている事を確認します
  • 手元でハンドリング出来る格子データ

    • オレオレフォーマットで可

gpmetisに渡すcellの接続情報を用意する

ここで作成したいのは以下のようなデータです。

graph.dat

        24      38              ←総node数、総edge数
         7         2    ←node 1 が接続しているnode番号。2つ隣接している
         8         3         1 ←node 2 が接続しているnode番号。3つ隣接している

        ...

node番号は1から数えます。

このdatファイルは以下のような格子に対応します。

格子とnode番号

graph.datに記述されているようにnode1は2、7と隣接しています。同様にnode2は1、3、8に隣接しています。

ここで、グラフ理論で言うところのnode/edgeと、有限体積法(FVM)で言うところのnode/edgeは意味が異なる点に注意します。ここではnode/edgeはグラフ理論における用語を指すことにします。例えばFVMでnodeと言えば通常は節点のことですが、ここでのnodeはCell-centered FVMにおけるcellに相当します。

それぞれ以下のように対応します。

  • グラフ:node = Cell-centered FVM:cell

  • グラフ:edge = Cell-centered FVM:隣接するcellを結んで出来る線、cell間の面

したがってgraph.datの「総node数」で指定するべき値はCell-centered FVMの「総cell数」であり、「総edge数」は「隣接するcellを結んで出来る線の総数」もしくは「境界を除くcell間の面の総数」となります。

左:node或いはcell 右:edge

もし使用している格子データに「総edge数」が含まれていない場合は別途数え上げる必要があります。

gpmetisで任意の領域数に分割する

「準備」で用意していたgpmetisコマンドを使って分割します。5つの領域に分割したい場合は端末で以下のように実行します。

gpmetis graph.dat 5

以下のようなファイルが生成されるはずです。

graph.dat.part.5

1  ← cell 1は領域1
1  ← cell 2は領域1
3  ← cell 3は領域3
...

ここで領域は0から数えます。

仮に並列化手法がMPIであれば各「領域」が「ランク」ということになります。

gpmetisの出力を使って元の格子を分割する

graph.datの出力を使って元の格子データを分割します。例として4分割したgraph.dat.part.4を読み込んで初めの格子に領域(ランク)を割り振り、色分けして出力してみます。

gpmetisの出力に従ってランクを割り当てた結果

綺麗に4等分してくれました。

もう少し複雑な例として非構造格子に適用してみます。こちらの記事で作成したものです。 

ここでは5分割してみます。

5分割した結果

どの程度均等に分割されたか確認してみます。

  rank0 rank1 rank2 rank3 rank4
Cell [%] 19.52  20.39  20.07  19.74  20.29 
面数 [%] 19.85  20.77  20.43  20.09  20.68 
節点数 [%] 21.80  23.00  22.60  22.20  23.00 

追加のオプションは指定していませんが十分な分割性能です。

※面と節点はrank境界で共有されている都合上、全rankの和は100%にはならないので大体です。

補足

大抵の場合、MPIでの並列計算に使用するためには各rank間で通信した情報を格納する余分なcellを各ランクで確保する必要があります。