18:30:54)追加された行はこの色です。削除された行はこの色です。現在(&lastmod;)作成中です。書いている内容も&color(#ff0000){大幅に変わる};可能性が高いので注意。引き続き、正方形領域の熱伝導問題(平衡温度分布)を解く例題を扱う。これまでMPIで並列化を行うにあたり、正方形領域のy方向(j方向)に複数の領域に分割し、それぞれの領域に一つずつMPIプロセスを割り当てて並列化していた。このような並列化を1次元領域分割による並列化という。下の図は正方形領域を16個の領域に分割した例である。同様に二次元領域分割による並列化も考えられる。正方形を16個の領域に2次元的に分割すると下の図のようになる。上の二つの図の場合、どちらも16個のMPIプロセスで並列化している。計算を早く終了させるためには、どちらが有利だろうか?今回はまずこのような、領域分割に基づく並列化を行う場合の、分割の次元数について考える。今考えている熱伝導問題の格子サイズMESH_SIZEが60、並列計算に利用出来るプロセッサコアの総数が100個あったとしよう。最大128コアを利用出来るジョブが投入できる。)この時、前回使った1次元領域分割に基づく並列化(thermal_diffusion.f90)はできない。y方向(j方向に)60個ある格子点を100個に分割することができないからである。2次元領域分割なら可能である。x方向(i方向)に10、y方向(j方向)に10、合計100個の領域に分割すれば、100個のコアを利用した並列計算が可能である。解くべき問題が3次元であれば(例えば立方体中の熱伝導問題など)、1次元で領域分割が不可能である場合も、2次元や3次元で領域分割が可能な場合がある。1000であれば、100個のコアを使った1次元領域分割は十分可能である。この場合、1次元領域分割と2次元領域分割は計算速度(答えを得るまでの時間)の点で同じであろうか?一つあたりのプロセッサが担当する(計算する)領域は全体正方形の1/100の面積に相当するので、どちらのやりかたで分割しても同じかと思うかもしれない。プロセス間の通信にかかる時間がゼロであればそのとおりだが、実際にはプロセス間の通信(MPI_SENDやMPI_RECV等)には有限の—それどころか結構長い—時間がかかる。1次元空間を格子点で離散化した上で、MPIでプロセス間通信を行う場合を考える。計算格子には2種類ある。一つは、その上で計算だけを行う格子。一つはMPI通信のデータを送ったり、受けたりする格子である。(一番外側から2番目の格子は計算も通信も行う。一つのMPIプロセスが行う通信の量は、通信を行う格子点の数に比例する。通信に時間がかかる場合、通信を行う格子点は少ないほうが望ましい。下の図は正方形領域を400個の格子点で離散化した場合を示す。これを4つのMPIプロセスで並列化することを考える。1次元領域分割の場合、下の図のようになる。2次元領域分割の場合、同じく4つのMPIプロセスで並列化すると、下の図のようになる。1次元領域分割の場合、一番下(赤色)のMPIプロセスが担当する長方形の領域の中で、通信をおこなう格子点は長方形の辺上にあるものである。数えてみるとその数は46個。2次元領域分割の場合、左下のMPIプロセス(赤色)が担当するのは正方形領域である。この中で通信をおこなう格子点はこの正方形の辺上にあるもので、数えてみると38個。1次元領域分割は2次元領域分割に比べて一つのプロセッサあたり46-38=8個の格子点数分だけ通信するデータ量が多い。プロセス間の通信速度が低い場合、できるだけ通信するデータの量を減らす必要がある。この点で、2次元領域分割の方が有利である。&color(#ff0000){実際には、コアとメモリ間との通信速度(キャッシュの利用効率)の影響等により、必ずしも2次元領域分割の方が速いというわけではない。&color(#ff0000){実際には、コアとメモリ間との通信速度(キャッシュの利用効率)の影響等により、必ずしも2次元領域分割の方が速いというわけではない。キャッシュの利用効率を上げる方法は研究の現場では重要なテーマであるが、この演習では取り上げない。同じMPIプロセス数による2次元領域分割でも様々な可能性がある。正方形を16個に分割するのだから、どちらも方法でも一つのMPIプロセスが担当する面積は等しい(元の正方形の16分の1)。下の二つの図を見ればわかるとおり、長方形よりも正方形に近い方が通信量が少ない。面積の等しい長方形の中で、4辺の長さの合計が最も小さいものは正方形である、という幾何学的事実を思い出せばこれは自明であろう。計算に要する時間やMPI通信に要する時間を測定する方法について説明する。これまで以下の二つの方法を説明した。mpi_wtimeは、MPIを用いた並列化プログラムのみで、しかもmpi_initを呼んだ後でしか使えなかったが、cpu_timeにはそのような制限がない。(ただしFotran95で導入された関数なので、古いFotran90コンパイラは対応していないかもしれない。これを見るとプログラム全体の実行時間(0番)のうち、ほとんどがヤコビ法の求解(3番)に費やされていることがわかる。領域分割による並列化を行うときに注意すべき点は、MPIプロセスの配置方法である。2次元領域分割の場合、あるプロセスに注目すると、最も頻繁に通信する相手は、隣(東西南北)の4つのプロセスである。隣同士の通信がもっとも通信速度的に「近い」位置にプロセスを配置することが望ましい。以下のようにプロセス(ランク番号)を配置した場合、4番のプロセスはランク番号1,3,5,7のプロセスと頻繁に通信することになる。使用している並列計算機のネットワークの設計上、4番のプロセスはむしろランク番号0,2,6,8のプロセスと通信した方が速い場合には、以下のようにプロセスを配置する方が望ましい。MPI関数の一つMPI_CART_CREATEを使うと、もしも使用する計算機がネットワークの通信性能の関する情報を提供している場合には、その情報を活用し通信効率の点で最適な配置でプロセスを自動的に分配してくれる。MPI_SENDRECV関数を用いて東西南北の4つの隣接プロセスと通信する。使用ノード数は1とする。今度は同じ計算を、10ノード(10個のプロセッサコア)を使い、10並列で計算してみよう。うち、次の2箇所を変える。オプションで10とする。10並列化することで計算速度が1/10になったことがわかる。MPIの通信に要する時間は全体の計算時間に比べたら無視できるほど小さい。今度は同じ計算を、64ノード(64個のプロセッサコア)を使った、64並列で計算してみよう。予想通り2次元領域分割の方が速い。見ると、常に1ノードに1つのコアを使っていた。1ノードに1つのコアを使う。"scalar"はデュアルコアプロセッサを並列に接続した計算機である。いちどscalarの構成を見てみよう。並列計算とは」p.17より引用。上のジョブスクリプトは、ディアルコアのうちひとつしか使っていないことを意味する。遊ばせておくのはもったいないので、ディアルコアの二つとも使ってみよう。ディアルコアプロセッサの二つのコアを使う方法は二つある。一つはMPIプロセスを二つ走らせる方法。一つはOpenMPでスレッドを二つ走らせる方法である。いずれの方法を取るにせよ、ノード間の並列化はMPIを使う。ノード間はMPIで、ノード内はOpenMPで並列化する後者の方法はhybrid並列化と呼ぶ。MPIを試してみよう。128個のMPIプロセスを64ノードで走らせる。ジョブスクリプトを少し変えるだけで良い。64ノード(128MPIプロセス)で計算した結果を下に示す。デュアルコアのうち一つのコアを遊ばせていた上記の場合(計算時間3.2秒)に比べると、ディアルコアを全部使いきったこの時、計算時間は半分とまでいかないが、2.4秒まで短縮された。ここまで並列化をすすめると、ヤコビ法のメインループにかかった時間(下の6番、約0.7秒)と比較して、MPI通信にかかる時間(下の4番、0.5秒)の割合はかなり大きい。MPI並列化を行った場合とデュアルコアの半分を遊ばせた場合との速度の比較を下のグラフに示した。次にhybrid並列化を試してみよう。OpenMPを使った並列計算」で学んだ方法で二つのスレッドにforkさせて計算すればよい。このときデュアルコアが二つとも仕事をしている。OpenMPによるスレッド並列化のためにコードに加える変更はわずかである。これは64ノードを使い、1ノードあたり1MPIプロセス、二つのOpenMPスレッドを走らせる時のスクリプトである。上のジョブスクリプトを使い、64ノードを使ったhybrid並列化による計算を行え。hybrid並列化を行うときのコンパイルコマンドは以下の通りである。MPIで計算した場合(約2.4)よりも20%近く高速化されている。(約157秒)に比べると80倍近い高速化である。コンパイルオプションを変えると、さらに高速化される。MPI並列化の方がhybrid並列化よりも速くなる。両者の計算速度を比較した図を下に示す。[#k801d0b1]今回の演習内容はどうでしたか?(どれか一つ、一度だけ押してください。[#o9c99adc]「お名前」欄は空欄で可。