mpi
cpi
先ずはmpichについているサンプルが動くかを確認する.
bob1 /home/bob> /usr/local/mpich/bin/mpirun -np 2 /usr/local/mpich/examples/cpi
と打ち込んでみて,
Process 0 on bob1.site Process 1 on bob2.site pi is approximately 3.1416009869231241, Error is 0.0000083333333309 wall clock time = 0.000000
となれば成功.Process 0 と1で並列計算されている.
hello.c
次に,もっとも簡単なプログラムである"Hello world!\n"を並列化する.MPIではprocess間でmessageをやり取りして,計算を進める.以下のプログラムでは,my_rank!=0なら子プロセスとなり,親(dest=0)に挨拶(message)を送る.親(my_rank==0)は挨拶を子プロセスの数(p)だけ受け取って,表示する.
#include <stdio.h>
#include <string.h>
#include "mpi.h"
main (int argc, char* argv[]){
int my_rank,p,source,dest,tag=0;
char message[100];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&p);
if (my_rank!=0){
sprintf(message, "Greetings from process %d!",my_rank);
dest = 0;
MPI_Send(message, strlen(message)+1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
} else {
for (source=1;source<p;source++){
MPI_Recv(message, 100, MPI_CHAR, source, tag, MPI_COMM_WORLD,&status);
printf("%s\n",message);
}
}
MPI_Finalize();
}
次のようにしてコンパイル,実行が可能.
mpicc hello.c mpirun -np 4 ./a.out
pi
台形公式にしたがって4/(1+x^2)の面積を求める.
#include <math.h>
#include <stdio.h>
double f1(double x);
int main(void){
int i,n;
double x=0,dx;
scanf("%d",&n);
dx=1.0/n;
double S=(f1(0)+f1(1))/2.0;
for (i=1;i<n;i++){
x+=dx;
S+=f1(x);
}
printf("%10d %20.15f\n",n,S*dx);
}
double f1(double x){
return 4.0/(1+x*x);
}
並列計算でPiを求めるコード.
#include <stdio.h>
#include <string.h>
#include "mpi.h"
double f1(double x);
double trapezoid(double a, double b, int n);
main (int argc, char* argv[]){
int my_rank,p,source,dest,tag=0,n;
double sum,sum1;
double local_a, local_b;
double startwtime=0.0, endwtime;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
MPI_Comm_size(MPI_COMM_WORLD,&p);
if (my_rank!=0){ //分割数の入力と通知
MPI_Recv(&n, 1, MPI_INT, source, tag, MPI_COMM_WORLD,&status);
} else {
printf("Input dividing number:");
scanf("%d",&n);
n = n/p;
printf("Dividing number per process:%10d\n",n);
for (dest=1;dest<p;dest++){
MPI_Send(&n, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
}
}
local_a=1.0/p*my_rank; //区間の割り出し
local_b=1.0/p*(my_rank+1);
startwtime = MPI_Wtime();
if (my_rank!=0){
sum=trapezoid(local_a,local_b,n); //子プロセスによる積分
dest = 0;
MPI_Send(&sum, 1, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
} else {
sum1=trapezoid(local_a,local_b,n); //親プロセスによる積分と和
for (source=1;source<p;source++){
MPI_Recv(&sum, 1, MPI_DOUBLE, source, tag, MPI_COMM_WORLD,&status);
// printf("Process %3d:%20.15f\n",source,sum);
sum1+=sum;
}
printf("Total:%20.15f\n",sum1);
endwtime = MPI_Wtime();
printf("wall clock time = %10.7f\n",endwtime-startwtime);
}
MPI_Finalize();
}
double trapezoid(double a, double b, int n){
int i;
double x=a,dx;
dx=(b-a)/n;
double S=(f1(a)+f1(b))/2.0;
for (i=1;i<n;i++){
x+=dx;
S+=f1(x);
}
// printf("%10d %20.15f\n",n,S*dx);
return S*dx;
}
double f1(double x){
return 4.0/(1+x*x);
}
mpirunの結果
bob1 bob/mpich> /usr/local/mpich/bin/mpirun -np 2 para_tra Input dividing number:1000000 Dividing number per process: 500000 Total: 3.141592653583196 wall clock time = 0.0273438
Keyword(s):
References:[LinuxEx]