ノード間並列
ここでは,内積計算プログラムが複数のRaspberry Pi上の複数のCPUコアを利用できるよう 拡張しましょう.これを,ノード間並列化と呼びます.
MPIとは
ノード内並列化と同様に,ノード間並列化にも様々な方法がありますが, スパコンにおいて広く用いられているのは,MPIと呼ばれるAPIです.
#include <stdio.h>
#include <mpi.h>
#define TRIALS (1000)
#define ARRAY_SIZE (1000 * 1000)
double a[ARRAY_SIZE];
double b[ARRAY_SIZE];
void compute()
{
int rank, nprocs;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &nprocs);
double sum = 0;
int subarray_size = ARRAY_SIZE / nprocs;
for (int i = subarray_size * rank; i < subarray_size * (rank + 1); i++) {
sum += a[i] * b[i];
}
double sum_total;
MPI_Reduce(&sum, &sum_total, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);
}
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
for (int i = 0; i < ARRAY_SIZE; i++) {
a[i] = 1.0;
b[i] = 2.0;
}
for (int i = 0; i < TRIALS; i++) {
compute();
}
MPI_Finalize();
return 0;
}
MPI版プログラムのコンパイル・実行
このプログラムをMPI用コンパイラでコンパイルします.
$ mpicc -o dot_mpi dot_mpi.c
MPIプログラム用ランチャでプログラムを起動し,実行時間を計測します.
$ time mpirun --hostfile hosts dot_mpi
OpenMPを使用しない場合の26.886秒に対して,3.377秒に実行時間を短縮できました. 4ノード上の計16のCPUコアを活用することで, 8.0倍の高速化を達成できたことになります.
real 0m3.377s
user 0m8.979s
sys 0m0.851s
MPIはデフォルトでは全てのノードの全てのCPUコアを用いて計算を行います.
mpirun
に-np
というオプションを指定することにより,
使用するコア数を制限することができます.
例えば,8コアを使用して計算を行うためには,次のようにします.
$ time mpirun -np 8 --hostfile hosts dot_mpi
やってみよう
-np
オプションを用いて使用するコア数を変更し,プログラムの実行時間がどのように変化するか調べてみましょう.