/*
   *       timing.c
   *
   *       Does a few communication timing tests on pvm.
   *       Uses `timing_slave' to echo messages.
   *
   *       9 Dec 1991  Manchek
   *  14 Oct 1992  Geist  - revision to pvm3
 */

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

#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <math.h>
#include "pvm3.h"


#define SLAVENAME "timing_slave"
#define SLAVEHOST "whoami"   /* enter machine name for slave here */

main (argc, argv)
     int argc;
     char **argv;
{
  int mytid;			/* my task id */
  int stid = 0;			/* slave task id */
  int reps = 20;		/* number of samples per test */
  struct timeval tv1, tv2;	/* for timing */
  int dt1, dt2;			/* time for one iter */
  int at1, at2;			/* accum. time */
  double res1, res2;		/* final results */
  int numint;			/* message length */
  int n;
  int i;
  int *iarray = 0;

  /* enroll in pvm */

  if ((mytid = pvm_mytid ()) < 0) {
    exit (1);
  }
  printf ("i'm t%x\n", mytid);


/* start up slave task */

  if (pvm_spawn (SLAVENAME, (char **) 0, 1, SLAVEHOST, 1, &stid) < 0
      || stid < 0) {
    fputs ("can't initiate slave\n", stderr);
    goto bail;
  }

  printf ("slave is task t%x\n", stid);

  /* round-trip timing test */

  puts ("Doing Round Trip test, minimal message size\n");
  at1 = 0;

  /* pack buffer */

  pvm_initsend (PvmDataRaw);
  pvm_pkint (&stid, 1, 1);

  puts (" N     uSec");
  for (n = 1; n <= reps; n++) {
    gettimeofday (&tv1, (struct timezone *) 0);

    if (pvm_send (stid, 1)) {
      fprintf (stderr, "can't send to \"%s\"\n", SLAVENAME);
      goto bail;
    }

    if (pvm_recv (-1, -1) < 0) {
      fprintf (stderr, "recv error%d\n");
      goto bail;
    }

    gettimeofday (&tv2, (struct timezone *) 0);

    dt1 = (tv2.tv_sec - tv1.tv_sec) * 1000000
      + tv2.tv_usec - tv1.tv_usec;
    printf ("%2d %8d\n", n, dt1);
    at1 += dt1;
  }
  printf ("Round Trip Test Avg uSec %d\n", at1 / reps);

  /*  bandwidth test for different message lengths */

  puts ("\nDoing Bandwidth test\n");

  numint = 25;			/* message size */
  printf ("\nMessage size %d\n", numint * 4);
  at1 = at2 = 0;
  iarray = (int *) malloc (numint * sizeof (int));
  puts (" N  Pack uSec  Send uSec");
  for (n = 1; n <= reps; n++) {
    gettimeofday (&tv1, (struct timezone *) 0);

    pvm_initsend (PvmDataRaw);
    pvm_pkint (iarray, numint, 1);

    gettimeofday (&tv2, (struct timezone *) 0);
    dt1 = (tv2.tv_sec - tv1.tv_sec) * 1000000
      + tv2.tv_usec - tv1.tv_usec;

    gettimeofday (&tv1, (struct timezone *) 0);

    if (pvm_send (stid, 1)) {
      fprintf (stderr, "can't send to \"%s\"\n", SLAVENAME);
      goto bail;
    }

    if (pvm_recv (-1, -1) < 0) {
      fprintf (stderr, "recv error%d\n");
      goto bail;
    }

    gettimeofday (&tv2, (struct timezone *) 0);
    dt2 = (tv2.tv_sec - tv1.tv_sec) * 1000000
      + tv2.tv_usec - tv1.tv_usec;

    printf ("%2d   %8d   %8d\n", n, dt1, dt2);
    at1 += dt1;
    at2 += dt2;
  }

  at1 /= reps;
  at2 /= reps;
  puts ("Avg uSec");
  printf ("     %8d   %8d\n", at1, at2);
  puts ("Avg Byte/uSec");
  if (at1 == 0)  /* avoid dividing by zero */
    res1 = 0;
  else
    res1 = (numint * 4) / (double) at1;

  if (at2 == 0)
    res2 = 0;
  else
    res2 = (numint * 4) / (double) at2;
  printf ("     %8f   %8f\n", res1, res2);


  puts ("\ndone");

bail:
  if (stid > 0)
    pvm_kill (stid);
  pvm_exit ();
  exit (1);
}

