/* 双子素数を求める */
#include <stdio.h>
#include <malloc.h>
#include <math.h>
#include <time.h>
#include "mpi.h"
int main(int argc, char **argv){
int myid, np;
double start, end, total_time; /* タイマー用変数 */
int zero, n; /* 0と範囲用変数 */
long recv_counter; /* 受信カウンター用変数 */
MPI_Status st;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
MPI_Comm_size(MPI_COMM_WORLD, &np);
if(argc != 2){
exit(-1);
}
/* 初期化 */
zero = 0;
n = atoi(argv[1]);
recv_counter=0; // MPI_Recvがあるたびに+1
/* タイマースタート */
MPI_Barrier(MPI_COMM_WORLD);
start = MPI_Wtime();
/* PE 0 */
if(myid == 0){
int i, x, prime;
/* 数の生成 */
/* 3以上の奇数を次のPEに送っている */
for(i = 3; i<n;i+=2){
MPI_Send(&i, 1, MPI_INT, 1, 1000, MPI_COMM_WORLD);
}
/* 番兵として最後に0を送る */
MPI_Send(&zero, 1, MPI_INT, 1, 1000, MPI_COMM_WORLD);
while(1){
MPI_Recv(&x, 1, MPI_INT, np-1, 1000, MPI_COMM_WORLD, &st);
recv_counter++;
/* 最初に受け取った数は素数 */
prime = x;
/* 最初に受け取った数が番兵(0)だったらループから出る */
if(x == 0){
MPI_Send(&zero, 1 ,MPI_INT, 1, 1000, MPI_COMM_WORLD);
break;
}
while(1){
MPI_Recv(&x, 1, MPI_INT, np-1, 1000, MPI_COMM_WORLD, &st);
recv_counter++;
/* 素数に2を足した数が来たら、それも素数 */
/* しかも双子素数なので、それらを表示する */
if(x == prime+2); //printf("%d and %d\n", prime, x);
/* 番兵(0)が来たらループから出る */
if(x == 0) {
MPI_Send(&zero, 1 ,MPI_INT, 1, 1000, MPI_COMM_WORLD);
break;
}
/* 2番目以降に受け取った数は素数を使ってふるい分ける */
if(x % prime != 0){
MPI_Send(&x, 1 ,MPI_INT, 1, 1000, MPI_COMM_WORLD);
}
}
}
}
/* 最後のPE */
else if(myid == np-1){
int i, x, prime;
while(1){
MPI_Recv(&x, 1, MPI_INT, myid - 1, 1000, MPI_COMM_WORLD, &st);
recv_counter++;
/* 最初に受け取った数は素数 */
prime = x;
/* 最初に受け取った数が番兵(0)だったらループから出る */
if(x == 0){
MPI_Send(&zero, 1 ,MPI_INT, 0, 1000, MPI_COMM_WORLD);
break;
}
while(1){
MPI_Recv(&x, 1, MPI_INT, myid - 1, 1000, MPI_COMM_WORLD, &st);
recv_counter++;
/* 素数に2を足した数が来たら、それも素数 */
/* しかも双子素数なので、それらを表示する */
if(x == prime+2); //printf("%d and %d\n", prime, x);
/* 番兵(0)が来たらループから出る */
if(x == 0) {
MPI_Send(&zero, 1 ,MPI_INT, 0, 1000, MPI_COMM_WORLD);
break;
}
/* 2番目以降に受け取った数は素数を使ってふるい分ける */
if(x % prime != 0){
MPI_Send(&x, 1 ,MPI_INT, 0, 1000, MPI_COMM_WORLD);
}
}
}
}
/* PEが0でもnp-1でもない場合 */
else{
int i, x, prime;
while(1){
MPI_Recv(&x, 1, MPI_INT, myid - 1, 1000, MPI_COMM_WORLD, &st);
recv_counter++;
/* 最初に受け取った数は素数 */
prime = x;
/* 最初に受け取った数が番兵(0)だったらループから出る */
if(x == 0){
MPI_Send(&zero, 1 ,MPI_INT, myid + 1, 1000, MPI_COMM_WORLD);
break;
}
while(1){
MPI_Recv(&x, 1, MPI_INT, myid - 1, 1000, MPI_COMM_WORLD, &st);
recv_counter++;
/* 素数に2を足した数が来たら、それも素数 */
/* しかも双子素数なので、それらを表示する */
if(x == prime+2) //printf("%d and %d\n", prime, x);
/* 番兵(0)が来たらループから出る */
if(x == 0) {
MPI_Send(&zero, 1 ,MPI_INT, myid +1, 1000, MPI_COMM_WORLD);
break;
}
/* 2番目以降に受け取った数は素数を使ってふるい分ける */
if(x % prime != 0){
MPI_Send(&x, 1 ,MPI_INT, myid +1, 1000, MPI_COMM_WORLD);
}
}
}
}
/* タイマーストップ */
MPI_Barrier(MPI_COMM_WORLD);
end = MPI_Wtime();
/* タイムとパケットの受信回数と自分のidを表示 */
total_time = end - start;
printf("Total time : %g seconds.\tcount:
%ld\tmyid:%d\n", total_time,recv_counter,myid);
/* 終了 */
MPI_Finalize();
}