pong.c - an MP_Lite example

Download pong.c sourcecode?


/*                  pong.c Generic Benchmark code
 *               Dave Turner - Ames Lab - July of 1994+++
 *                        (turner@ameslab.gov)
 *
 *  Most Unix timers cannot be trusted for very short times, so take this
 *  into account when looking at the results.  This code also only times
 *  a single message passing event for each size, so the results may vary
 *  between runs.  For more accurate measurements, please grab NetPIPE from
 *  http://www.scl.ameslab.gov/ .
 */

int main(int argc, char *argv[])
{
   int myproc, end_node, size, other_node, nprocs, i, last, tag = 0;
   double t1,t2,time, MP_Time();
   double *a, *b, *c;
   double max_rate = 0.0, min_latency = 10e6;
   int isid, irid, irid_a, irid_b;

#if defined (_CRAYT3E)
   a = (double *) shmalloc(132000*sizeof(double));
   b = (double *) shmalloc(132000*sizeof(double));
#else
   a = (double *) malloc(132000*sizeof(double));
   b = (double *) malloc(132000*sizeof(double));
#endif

   for(i=0; i < 132000; i++) {
      a[i] = (double) i;
      b[i] = 0.0;
   }

   MP_Init(&argc, &argv);
   MP_Myproc( &myproc );
   MP_Nprocs( &nprocs );

   if( nprocs != 2) exit(1);
   other_node = (myproc+1)%2;

/*   printf("Hello from %d of %d\n",myproc, nprocs);*/
   MP_Sync();

/* Timer accuracy test */

   t1 = MP_Time();
   t2 = MP_Time();
   while( t2 == t1 ) t2 = MP_Time();
   if( myproc == 0 ) printf("Timer accuracy of ~%f usecs\n\n", (t2-t1)*1000000);

/* Communication tests between nodes 
 *   - Blocking sends and recvs
 *   - No guarantee of a preposted recv, so it might pass through comm buffer
 */

   for(size=8;size < = 1048576;size*=2) {

      for( i=0; i < size/8; i++) { a[i] = (double) i; b[i] = 0.0;}
      last = size/8 - 1;
      a[0] -= 1.0; if (last != 0) a[last] -= 1.0;

      MP_Sync();
      t1=MP_Time();

      if (myproc == 0) {                /* Send first, then receive */
         MP_Send(a, size, other_node, tag);
         tag++;
         MP_Recv(b, size, other_node, tag);
      } else {                          /* Receive first, then send */
         MP_Recv(b, size, other_node, tag);
         b[0] += 1.0; if (last != 0) b[last] += 1.0;
         tag++;
         MP_Send(b, size, other_node, tag);
      }

      t2=MP_Time();
      time=1.e6*(t2-t1);
      MP_Sync();

         /* Check the message for integrity */

      for(i=0; i < last; i++) {
         if( b[i] != (double) i ) {
            printf("Node %d ERROR - b[%d] = %f\n", myproc, i, b[i]);
            exit(1);
         }
      }

         /* Print out the time.  Not real accurate for small messages */

      if (myproc == 0 && time > 0.000001) {
         printf(" %7d bytes took %9.0f usec (%8.3f MB/sec)\n",
                                 size,time,2.0*size/time);
         if( 2*size/time > max_rate ) max_rate = 2*size/time;
         if( time/2 < min_latency ) min_latency = time/2;
      } else if (myproc==0) {
         printf(" %7d bytes took less than the timer accuracy\n",size);
      }
   }

/* Asynchronous communications
 *   - Prepost receives to guarantee bypassing the comm buffer
 */

   MP_Sync();
   if( myproc==0) printf("\n  Asynchronous ping-pong\n\n");

   for(size=8;size < = 1048576;size*=2) {

      for( i=0; i < size/8; i++) { a[i] = (double) i; b[i] = 0.0;}
      last = size/8 - 1;
      a[0] -= 1.0; if (last != 0) a[last] -= 1.0;
      tag++;

      MP_ARecv(b, size, other_node, tag, &irid);
      MP_Sync();
      t1=MP_Time();

      if (myproc == 0) {   /* Send first, then wait for the recv to complete */
         MP_Send(a, size, other_node, tag);
         MP_Wait(&irid);
      } else {             /* Wait for the recv, then send the data back */
         MP_Wait(&irid);
         b[0] += 1.0; if (last != 0) b[last] += 1.0;
         MP_Send(b, size, other_node, tag);
      }

      t2=MP_Time();
      time=1.e6*(t2-t1);
      MP_Sync();

         /* Check the message for integrity */

      for(i=0; i < last; i++) {
         if( b[i] != (double) i ) {
            printf("Node %d ERROR - b[%d] = %f\n", myproc, i, b[i]);
            exit(1);
         }
      }

      if (myproc == 0 && time > 0.000001) {
         printf(" %7d bytes took %9.0f usec (%8.3f MB/sec)\n",
                                 size,time,2.0*size/time);
         if( 2*size/time > max_rate ) max_rate = 2*size/time;
         if( time/2  <  min_latency ) min_latency = time/2;
      } else if (myproc==0) {
         printf(" %7d bytes took less than the timer accuracy\n",size);
      }
   }

/* Bidirectional communications
 *   - Communicate in both directions at the same time
 *     using asynchronous communications
 */

   if( myproc==0) printf("\n  Bi-directional asynchronous ping-pong\n\n");

   for(size=8;size < = 1048576;size*=2) {

      for( i=0; i < size/8; i++) { a[i] = (double) i; b[i] = 0.0;}
      last = size/8 - 1;
      a[0] -= 1.0; if (last != 0) a[last] -= 1.0;
      tag++;

      MP_ARecv(b, size, other_node, tag, &irid_b);
      MP_ARecv(a, size, other_node, tag+1, &irid_a);
      MP_Sync();
      t1=MP_Time();
 
         MP_Send(a, size, other_node, tag);
         MP_Wait(&irid_b);
 
         b[0] += 1.0; if (last != 0) b[last] += 1.0;
         tag++;
 
         MP_Send(b, size, other_node, tag);
         MP_Wait(&irid_a);
 
      t2=MP_Time();
      time=1.e6*(t2-t1);
      MP_Sync();

         /* Check the message for integrity */

      for(i=0; i < last; i++) {
         if( b[i] != (double) i ) {
            printf("Node %d ERROR - b[%d] = %f\n", myproc, i, b[i]);
            exit(1);
         }
      }

      if (myproc == 0 && time > 0.000001) {
         printf(" %7d bytes took %9.0f usec (%8.3f MB/sec)\n",
                                 size,time,2.0*size/time);
         if( 2*size/time > max_rate ) max_rate = 2*size/time;
         if( time/2  <  min_latency ) min_latency = time/2;
      } else if (myproc==0) {
         printf(" %7d bytes took less than the timer accuracy\n",size);
      }
   }
 
   if( myproc==0) printf("\n Max rate = %f MB/sec  Min latency = %f usec\n",
                         max_rate, min_latency);

   MP_Finalize(); 
}