This source file includes following definitions.
- nice_send
- nice_recv
- nice_barrier
- main
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 #include <unistd.h>
  13 #include <stdlib.h>
  14 #include <stdio.h>
  15 #include <string.h>
  16 #include <time.h>
  17 #include <sys/utsname.h>
  18 
  19 #include <mpi.h>
  20 
  21 #define NCHARS 30
  22 const int max_depth = 4;
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 static int nice_send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) {
  36     
  37     return MPI_Send(buf, count, datatype, dest, tag, comm);
  38 }
  39 
  40 
  41 static int nice_recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) {
  42     MPI_Request req;
  43     int flag;
  44     struct timespec dt;
  45 
  46     
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54     dt.tv_sec    =       0;
  55     dt.tv_nsec   =  100000;
  56 
  57     MPI_Irecv(buf, count, datatype, source, tag, comm, &req);
  58 
  59     MPI_Test(&req, &flag, status);
  60     while ( ! flag ) {
  61         nanosleep(&dt, NULL);
  62         MPI_Test(&req, &flag, status);
  63     }
  64     return MPI_SUCCESS;
  65 }
  66 
  67 
  68 static void nice_barrier(MPI_Comm comm) {
  69     int me, np, jump, buf = -1;
  70 
  71     MPI_Comm_rank(comm,&me);
  72     MPI_Comm_size(comm,&np);
  73 
  74     
  75     for ( jump = 1; jump < np; jump <<= 1 ) {
  76         if ( ( me & jump ) != 0 ) {
  77             nice_send(&buf, 1, MPI_INT, me - jump, 343, comm);
  78             break;
  79         } else if ( me + jump < np ) {
  80             nice_recv(&buf, 1, MPI_INT, me + jump, 343, comm, MPI_STATUS_IGNORE);
  81         }
  82     }
  83 
  84     
  85     if ( 0 != me ) {
  86         nice_recv(&buf, 1, MPI_INT, me - jump, 344, comm, MPI_STATUS_IGNORE);
  87     }
  88     jump >>= 1;
  89     for ( ; jump > 0; jump >>= 1 ) {
  90         if ( me + jump < np ) {
  91             nice_send(&buf, 1, MPI_INT, me + jump, 344, comm);
  92         }
  93     }
  94 }
  95 
  96 
  97 int main (int argc, char **argv)
  98 {
  99     char bufs   [NCHARS];               
 100     char bufr[2][NCHARS];               
 101     MPI_Comm parent;
 102     int level = 0, participate = 1;
 103     struct utsname buf;
 104 
 105     
 106 #if defined(OPEN_MPI)
 107     if (OMPI_MAJOR_VERSION < 2) {
 108         printf("Skipping, because the orte cannot handle concurrent MPI_Comm_spawns\n");
 109         return 77;
 110     } else {
 111         printf("Verify that this test is truly working because conncurrent MPI_Comm_spawns"
 112                " has not worked before.\n");
 113     }
 114 #endif
 115 
 116     uname(&buf);
 117     printf("I AM pid %d with level %d on %s\n", getpid(), (argc < 2)?0:atoi(argv[1]), buf.nodename);
 118 
 119     MPI_Init(&argc, &argv);
 120     MPI_Comm_get_parent(&parent);
 121 
 122     if (MPI_COMM_NULL != parent) {
 123         
 124         level = atoi(argv[1]);
 125         MPI_Recv(&bufr[0], sizeof(char)*NCHARS, MPI_CHAR, MPI_ANY_SOURCE,
 126                  MPI_ANY_TAG, parent, MPI_STATUS_IGNORE);
 127         printf("Parent sent: %s\n", bufr[0]);
 128     } else {
 129 
 130         
 131 
 132         
 133 
 134 
 135 
 136 
 137 
 138 
 139 
 140 
 141 
 142 
 143         int me, np;
 144 
 145         MPI_Comm_size(MPI_COMM_WORLD,&np);
 146         MPI_Comm_rank(MPI_COMM_WORLD,&me);
 147 
 148         if ( np > 4 ) {
 149             
 150             if ( ( me & 3 ) != 0 ) participate = 0;
 151         } else
 152         if ( np > 2 ) {
 153             
 154             if ( ( me & 1 ) != 0 ) participate = 0;
 155         }
 156     }
 157 
 158     
 159     if ( participate ) {
 160         printf("level = %d\n", level);
 161 
 162         
 163         sprintf(bufs,"level %d (pid:%d)", level, getpid());
 164 
 165         
 166         if (level < max_depth) {
 167             int i, nspawn = 2, errcodes[1];
 168             MPI_Request req[2];
 169             MPI_Comm   comm[2];
 170             char argv1[NCHARS];
 171             char *args[2];
 172 
 173             
 174             if ( level == 0 ) nspawn = 1;
 175 
 176             
 177             snprintf(argv1, sizeof(argv1), "%d", level+1);
 178             args[0] = argv1;
 179             args[1] = NULL;
 180 
 181             
 182             for ( i = 0; i < nspawn; i++ ) {
 183                 MPI_Comm_spawn(argv[0], args, 1, MPI_INFO_NULL, 0, MPI_COMM_SELF,
 184                                &comm[i], errcodes);
 185                 MPI_Send(&bufs, sizeof(char)*NCHARS, MPI_CHAR, 0, 100, comm[i]);
 186                 MPI_Irecv(&bufr[i], sizeof(char)*NCHARS, MPI_CHAR, MPI_ANY_SOURCE,
 187                           MPI_ANY_TAG, comm[i], &req[i]);
 188             }
 189 
 190             
 191             MPI_Waitall(nspawn, req, MPI_STATUSES_IGNORE);
 192             for ( i = 0; i < nspawn; i++ )
 193                 printf("Child %d sent: %s\n", i, bufr[i]);
 194         }
 195 
 196         
 197         if (MPI_COMM_NULL != parent) {
 198             MPI_Send(&bufs, sizeof(char)*NCHARS, MPI_CHAR, 0, 100, parent);
 199         }
 200     }
 201 
 202     
 203     
 204     if (MPI_COMM_NULL == parent) {
 205         nice_barrier(MPI_COMM_WORLD);
 206     }
 207 
 208     MPI_Finalize();
 209     return 0;
 210 }