#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
#include <sys/time.h>

static struct timeval time_value1;
static struct timeval time_value2;
#define START_TIMER gettimeofday(&time_value1, (struct timezone*)0)
#define STOP_TIMER gettimeofday(&time_value2, (struct timezone*)0)
#define ELAPSED_TIME ((double) ((time_value2.tv_usec - \
            time_value1.tv_usec)*0.001 \
            + ((time_value2.tv_sec - time_value1.tv_sec)*1000.0)))

static char *buffer;
static int iproc;
static int nproc;
double roundtrip(int count, int size)
{
   MPI_Status status;

   int i;
   START_TIMER;
   if ( iproc == 0 ) 
   {
      for (i = 0 ; i < count ; i++) 
      {
         MPI_Send(buffer, size, MPI_BYTE, 1, 0, MPI_COMM_WORLD);
         MPI_Recv(buffer, size, MPI_BYTE, 1, 0, MPI_COMM_WORLD, 
            &status);
      }

   } 
   else 
   {
      for (i = 0 ; i < count ; i++) 
      {

         MPI_Recv (buffer, size, MPI_BYTE, 0, 0, MPI_COMM_WORLD, 
            &status);

         MPI_Send (buffer, size, MPI_BYTE, 0, 0, MPI_COMM_WORLD);

      }

   }
   STOP_TIMER;

   return (ELAPSED_TIME / ((double) count));
}

int main(int argc, char *argv[])
{
   int count ;

   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &nproc);
   MPI_Comm_rank(MPI_COMM_WORLD, &iproc);

   if (argc != 2)
      perror("Usage: roundTrip <Number of iterations>");

   count = atoi (argv[1]);

   if (nproc != 2)
      perror("Fatal run time error: number of processors must be two");

   /* allocate a buffer of size 1 MByte */
   {
      double *p;
      int i ;
      double elapsed_time;
      p = (double *) malloc(1024 * 128 * sizeof(double));

      if (!p)
         perror ("Malloc failed");

      /* fill buffer with some arbitrary values */
      buffer = (char *) p;

      for (i = 0 ; i < 1024 * 1024 ; i++) buffer[i] = 1;

      /* measure times */
      if ( iproc == 0 ) printf("Bytes\t\tElapsed Time (mS)\n");
      for ( i = 2 ; i < 1024 * 1024 ; i *= 2 ) 
      {
         elapsed_time = roundtrip(count, i);
         if (iproc == 0) 
         {
            printf ("%d\t\t%.4f\n", i, elapsed_time);
            fflush ( stdout );
         }
      }
      free ( p ) ;
   }
   MPI_Finalize () ;

   return 0;
}

