SHMEMmer Wanna Be

My Journey To Understanding and Using SHMEM:

Lesson 5: Atomic Functions

Atomic Functions like communication functions can only be applied to objects in the symmetric memory. Unlike reduction calls which includes all PEs in a group, atomic functions are one-sided. Actually, it is very similar to a put call with a destination PE; however, with atomic, as the name would suggest, only one PE can change the destination value at a time. (We will only be focusing on the non-fetching routines.)

There are four operations which we will focus on: add, and, or, xor. These atomic operations are called via the following:

A few things to note:
  1. only one value is changed - you are sending one value to be "added" to the content at the destination address.
  2. the caller is only accessing the data of only one PE (the dest_pe)

Approximating pi revisited:

Rather than sending each individual count to PE 0 and having PE 0 add up the values, each PE (including PE 0) will call an atomic add. As a result, the value total on PE0 will be the sum of all the individual counts.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <inttypes.h>

#include <shmem.h>

#define NUM 100000

double circle(double x){
	return 1 - pow(x,2);
}

int main(){
    int me, npes;
    shmem_init();
    me = shmem_my_pe();
    npes = shmem_n_pes();

    static long count = 0;
    double f_x;

    //seed the randomizer
    srand(time(0)+me);
    for (int i = 0; i < NUM; i++){
        //generate point(x,y) in first quadrant
        //note: double is a 64 bit floating point
        double x = (double) rand() / (double) RAND_MAX;
        double y = (double) rand() / (double) RAND_MAX;
        f_x = circle(x);
        if (pow(y,2) <= f_x){
            count += 1;
        }
    }

    printf("%d: count %ld\n", me, count);
    static long total = 0; //needs to be in symmetric memory
    
    shmem_long_atomic_add(&total, count, 0);
    
    shmem_barrier_all(); //making sure all of the counts have been done
    if (me == 0){
        printf("%d: count total: %ld\n", me, total);
        printf("%d: ratio: %f\n", me, (double)total/((double)NUM * npes));
        printf("%d: est of pi: %f\n", me, (double)total/((double)NUM * npes)*4);
    }
    return 0;
}