8台、各マシン4ノードの全32ノードで試したら、分割数が増えるに従って、急速にスピードが落ちた。
そのときの実行結果を再掲しておく。
$ mpiexec -hostfile host32 python3 near_pi_gather_ov.py 1000000
総数 32000000 = 32 * 1000000
1分割 円周率:3.1422670000 9.170秒
2分割 円周率:3.1417440000 8.220秒
5分割 円周率:3.1418595000 8.787秒
10分割 円周率:3.1418603750 10.083秒
20分割 円周率:3.1415906250 12.403秒
50分割 円周率:3.1416473750 21.225秒
100分割 円周率:3.1412976250 34.077秒
200分割 円周率:3.1416820000 66.294秒
500分割 円周率:3.1420510000 165.598秒
1000分割 円周率:3.1415998750 329.557秒
同じことを、8台、各マシン2ノードの全16ノードで試した。全体の試行回数が同じになるように、各マシンでは、2倍の2000000回試行した。
$ cat host16_2
RP0 slots=2
RP1 slots=2
RP2 slots=2
RP3 slots=2
RP4 slots=2
RP5 slots=2
RP6 slots=2
RP7 slots=2
$ mpiexec -hostfile host16_2 python3 near_pi_gather_ov.py 2000000
総数 32000000 = 16 * 2000000
1分割 円周率:3.1417561250 7.175秒
2分割 円周率:3.1410828750 7.097秒
5分割 円周率:3.1419647500 7.143秒
10分割 円周率:3.1414366250 7.707秒
20分割 円周率:3.1407711250 8.873秒
50分割 円周率:3.1416947500 10.956秒
100分割 円周率:3.1410940000 14.920秒
200分割 円周率:3.1418913750 21.310秒
500分割 円周率:3.1410143750 52.542秒
1000分割 円周率:3.1417328750 100.665秒
上限の32ノードよりも、各マシンのノード数を半分に減らしたほうが、すべての場合に高速になった。ノード数をどんどん増やせば性能が上がる訳ではない。
同じことを、8台、各マシン1ノードの全8ノードで試した。全体の試行回数が同じになるように、各マシンでは、4倍の4000000回試行した。
$ cat host8_1
RP0 slots=1
RP1 slots=1
RP2 slots=1
RP3 slots=1
RP4 slots=1
RP5 slots=1
RP6 slots=1
RP7 slots=1
$ mpiexec -hostfile host8_1 python3 near_pi_gather_ov.py 4000000
総数 32000000 = 8 * 4000000
1分割 円周率:3.1414306250 8.161秒
2分割 円周率:3.1416215000 7.584秒
5分割 円周率:3.1413658750 7.133秒
10分割 円周率:3.1415557500 6.800秒
20分割 円周率:3.1418298750 7.254秒
50分割 円周率:3.1413220000 7.435秒
100分割 円周率:3.1419230000 8.711秒
200分割 円周率:3.1421395000 9.170秒
500分割 円周率:3.1419243750 13.161秒
1000分割 円周率:3.1415615000 19.557秒
各マシンでのコア数を十分少なくした方が良さそうな感じだ。
次に、全体のノード数を4台に絞って調べていこう。
細かい説明は省略する。
$ mpiexec -n 4 python3 near_pi_gather_ov.py 8000000
総数 32000000 = 4 * 8000000
1分割 円周率:3.1412775000 10.418秒
2分割 円周率:3.1415326250 10.720秒
5分割 円周率:3.1416202500 13.650秒
10分割 円周率:3.1414942500 13.000秒
20分割 円周率:3.1418226250 12.196秒
50分割 円周率:3.1413615000 13.603秒
100分割 円周率:3.1416942500 15.120秒
200分割 円周率:3.1412256250 19.480秒
500分割 円周率:3.1418320000 21.470秒
1000分割 円周率:3.1417106250 27.180秒
$ mpiexec -H RP0,RP1,RP2,RP3 python3 near_pi_gather_ov.py 8000000
総数 32000000 = 4 * 8000000
1分割 円周率:3.1414535000 13.741秒
2分割 円周率:3.1409381250 14.580秒
5分割 円周率:3.1420821250 15.083秒
10分割 円周率:3.1414958750 13.676秒
20分割 円周率:3.1417526250 13.509秒
50分割 円周率:3.1420788750 13.870秒
100分割 円周率:3.1415277500 14.460秒
200分割 円周率:3.1414960000 14.370秒
500分割 円周率:3.1415401250 15.159秒
1000分割 円周率:3.1420296250 18.887秒
分割数が多い(通信頻度が多い)場合、ノード数を増やして各ノードの負荷を減らしても、通信のオーバーヘッドの方が遥かに多くなるようだ。
また、1台のコンピュータでのノード数が増えても、ノード数に従って直線的に性能が上昇する訳ではない。リソースに少し余裕がある方が良いようだ。
全体のノード数が同数の場合、1つのコンピュータにまとまっていた方が、高速になっている。これは、ノード間の通信が、ネットを経由する必要がないためであろう。
MPIは便利だが、通信負荷はかなり大きいので、多用しないよう気をつけて使う必要がありそうだ。
次から、ナンプレの問題生成というかなり負荷の高い処理を、MPIを使って分散生成してみよう。