SHMEMmer Wanna Be

My Journey To Understanding and Using SHMEM:

Lesson 3: An Introduction to Barriers

Hold up!!! I need that tool! Many times before a processor can start a task, it must be ensured that it has the correct data. For instance, if a processor was to add A=3 and B=4, but another processor decided to change B to 1, the resultant sum would be wrong. OR if a processor was to add up all of the values given to it by the other processors, it would be nice to know that it actually received all of the new values. In both of these scenarios, a barrier of some sort would be beneficial.

In shmem, there are a few types of barriers useful for a variety of occasions.

Barriers/Synchronization across all or a subset of PEs: Barriers/Synchronization until data has changed (only concerned with one PE): Lets look at the first set one at a time. (The second set will be discussed in the next lesson.)

1. shmem_barrier_all()

2. shmem_barrier(int PE_start, int logPE_stride, int PE_size, long *pSync)

//barrier.c

  #include <stdio.h>
  #include <shmem.h>
  
  int main()
  {

      //creating pSync arrays for both groups
      static long pSync_odd[SHMEM_BARRIER_SYNC_SIZE];
      static long pSync_even[SHMEM_BARRIER_SYNC_SIZE];
      
      //initializing pSync arrays
      for (int i = 0; i < SHMEM_BARRIER_SYNC_SIZE; i++){
          pSync_odd[i] = SHMEM_SYNC_VALUE;
          pSync_even[i] = SHMEM_SYNC_VALUE;
      }
  
      shmem_init();
      int my_pe = shmem_my_pe();
      int num_pes = shmem_n_pes();

      //symmetric space
      static int num_of_scalpel_injuries; 
      static int num_of_ice_cream_scoop_injuries; 

      //if odd:
      if (my_pe%2 != 0){
          num_of_scalpel_injuries = my_pe-1;
          //sync all odd to make sure everyone has written down their answer
          //to the number of scalpel injuries survey
          shmem_barrier(1, 1, (num_pes/2), pSync_odd);
          int num_of_neighbor = shmem_int_g(&num_of_scalpel_injuries, (my_pe+2)%10);
          printf("%d: I personally had only %d scalpel injuries in my line of \
                  work whereas my odd neighbor had %d.\n", 
                  my_pe, num_of_scalpel_injuries, num_of_neighbor);
      }
      //if even and not 0
      else if (my_pe != 0){  
          num_of_ice_cream_scoop_injuries = my_pe;
          //sync all even to make sure everyone has written down their answer
          //to the number of ice cream scoop injuries survey
          shmem_barrier(2, 1, ((num_pes-2)/2 + num_pes % 2), pSync_odd);
          int num_of_neighbor; 
          if (my_pe == 2){ 
              num_of_neighbor = shmem_int_g(&num_of_ice_cream_scoop_injuries,8);
          } else {
              num_of_neighbor = shmem_int_g(&num_of_ice_cream_scoop_injuries, my_pe-2);
          }
          printf("%d: Yay! I am not the only one who hurts themselves with an \
                  ice cream scoop! My neighbor has done it %d times.\n", 
                  my_pe, num_of_neighbor);
      }
      

      shmem_finalize();	
      return 0;
  }


To compile:
        oshcc barrier.c -o barrier
To run:
        oshrun -np 10 barrier



The above code splits the 10 PEs into two groups, as afore mentioned: (1,3,5,7,9) and (2,4,6,8). Suppose the odd group wants to know how many scalpel injuries their neighbor (to the right) had. Now, lets be honest, we all accidentally cut our lab partners in Biology class.

Whereas, the even group is a bit more civilized and they just want to know if their neighbor (to the left, excluding 0) has ever hurt themselves with an ice cream scoop (I may have just done this . . .).

To note:

3. shmem_sync_all()

4. shmem_sync(int PE_start, int logPE_stride, int PE_size, long *pSync)