/* L-7 MCS 572 Wendesday 25 January 2006 measure time for one send/recv 
 * of a 2520-by-2520 matrix of random doubles.
 * Compile as "mpicc cost_one_sr.c -o cost_one_sr"
 * and run as "mpirun -np 2 cost_one_sr". */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "mpi.h"

#define size 2520  /* size of the problem, divisible by 2,3,4,..,10 */
#define tag 100    /* tag for sending a number */

void random_matrix ( int n, int m, double *a );
/* generates a random n-by-m matrix */

void print_time ( int p, double time[p] );
/* prints the timing results in the array time of size p */

int main ( int argc, char *argv[] )
{
   int myid,p;
   double *wall_time,startwtime,endwtime,wtime;
   double *A = (double*)calloc(size*size,sizeof(double));
   MPI_Status status;

   MPI_Init(&argc,&argv);
   MPI_Comm_size(MPI_COMM_WORLD,&p);
   MPI_Comm_rank(MPI_COMM_WORLD,&myid);

   srand(time(NULL));

   if(myid==0) /* manager allocates and initializes matrix and vector */
   {
      wall_time = (double*) calloc(p,sizeof(double));
      startwtime = MPI_Wtime();
      random_matrix(size,size,A);
   }
   else
      startwtime = MPI_Wtime();

   if(myid==0)
      MPI_Send(A,size*size,MPI_DOUBLE,1,tag,MPI_COMM_WORLD);
   else if(myid==1)
      MPI_Recv(A,size*size,MPI_DOUBLE,0,tag,MPI_COMM_WORLD,&status);

   endwtime = MPI_Wtime();
   wtime = endwtime - startwtime;
   MPI_Gather(&wtime,1,MPI_DOUBLE,wall_time,1,MPI_DOUBLE,0,MPI_COMM_WORLD);
   if(myid==0) print_time(p,wall_time);

   MPI_Finalize();
   return 0;
}

void print_time ( int p, double time[p] )
{
   int i;

   printf("\nTotal wall time = %lf seconds on %d processors\n",time[0],p);
   for(i=1; i<p; i++)
      printf("Wall time on processor %d = %lf seconds.\n",i,time[i]);
}

void random_matrix ( int n, int m, double *a )
{
   int i,j;
   double *p;

   p = a;
   for(i=0; i<n; i++)
      for(j=0; j<m; j++)
         *(p++) = ((double) rand())/RAND_MAX;
}
