プログラム

/* 双子素数を求める */

#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();
}