センリュウのホームページへ ようこそ!
MPIプログラミング
コンパイルの方法
作成したMPIプログラム(並列コンピューター用プログラム)のコンパイルは、SCoreについてくるMPICH-1.2.0ライブラリを使って行います。
そのためには、/opt/score/mpi/mpich-1.2.0/i386-redhat7-linux2_4/examplesにあるMakefileをコピーして、作業ディレクトリに置いてください。
# make test でtest.cをコンパイルできます。
実行は、# scout -g pcc としておいて、 # scrun -nodes=3 ./test 等々。
プログラミング例
下のプログラミング例は、台形公式を使って関数(y=x*x)の積分を行うというものです。積分区間を均等に各プロセスに分配して計算させます。なお実行のさい、オプションには積分の始点と終点をつけるようになっています。
同じプログラムが各プロセスにコピーされて動くので、下の例ではmy_rankで自分が何者であり何をすればよいかを判断させるようになっています(ここではmy_rankが0ならサーバーといった具合)。MPIプログラムは基本的にこのパターンを使います。
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
main(int argc, char** argv) {
int my_rank;
int p;
double a; // 積分の始点
double b; // 積分の終点
double h;
double local_a;
double local_b;
int n = 4096; // 各プロセスで計算する台形数
double integral;
double total;
int source;
int dest = 0;
int tag = 0;
MPI_Status status;
double Trapezoid(double local_a, double local_b, int n, double h);
if(argc < 3) {
fputs("useage : program-name <start-point> <end-point>\n", stderr);
exit(1);
}
a = atof(argv[1]);
b = atof(argv[2]);
MPI_Init(&argc, &argv); //MPIの開始
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); //プロセスのランク(ホストナンバー)をmy_rankに得る
MPI_Comm_size(MPI_COMM_WORLD, &p); //プロセスの総数をpに得る
h = (b-a)/p;
local_a = a + my_rank*h;
local_b = local_a + h;
h = h/n;
integral = Trapezoid(local_a, local_b, n, h);
if (my_rank == 0) {
total = integral;
for (source = 1; source < p; source++) {
MPI_Recv(&integral, 1, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, &status); //受信
total = total + integral;
}
} else {
MPI_Send(&integral, 1, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD); //送信
}
if (my_rank == 0) {
printf("With n = %d trapezoids, our estimate\n", n*p);
printf("of the integral from %f to %f = %f\n", a, b, total);
}
MPI_Finalize(); //MPIの終了
}
//////////////////////////////////////////////////////////
double Trapezoid(double local_a, double local_b, int n, double h) {
double integral;
double x;
int i;
double func(double x);
integral = (func(local_a) + func(local_b))/2.0;
x = local_a;
for (i = 1; i <= n-1; i++) {
x = x + h;
integral = integral + func(x);
}
integral = integral*h;
return integral;
}
//////////////////////////////////////////////////////////
double func(double x) {
double return_val;
return_val = x*x; //ここに、積分する関数を記入
return return_val;
}
履歴 2002/05 作成