// Adsmith sample program; not intended to be efficient // finds the sum of an array of integers // each node works on its range of numbers, adding its partial sum to a // shared sum at the end // written here in SPMD style, but this is not necessary // necessary includes #include #include #include #include "adsm.h" #include "adsmutil.h" #include "adsmtime.h" // the following variables are shared in the Adsmith sense; note that // we access them via pointers, which are returned to us by // calls to adsm_malloc() int **X; // array of pointers to the integers to be summed int *NPtr, // pointer to length of array *NNodesPtr, // pointer to number of nodes in computation *SumPtr; // pointer to overall sum // the following variables are not shared in the Adsmith sense, though // they will have the same (unchanging) values at every node int N,NNodes; // the following variable is not shared in the Adsmith sense, and in // fact has different values at each node int Me; // number of this node // declare an instance of Adsmith's built-in barrier class, AdsmBarrier AdsmBarrier PrintBarr("printbar"); // declare an instance of Adsmith's built-in mutex (lock/unlock) class, // AdsmMutex AdsmMutex CompCountMtx("ccmutex"); Worker() { int First,Last,I,Block,MySum=0; // set up the block for this node to sum Block = N / NNodes; First = Me * Block; Last = First + Block - 1; for (I = First; I <= Last; I++) { adsm_refresh(X[I]); MySum += *X[I]; } CompCountMtx.lock(); // need atomic access to *SumPtr adsm_refresh(SumPtr); // get latest sum value *SumPtr += MySum; adsm_flush(SumPtr); // update the other nodes CompCountMtx.unlock(); // end of critical section } int main(int argc, char **argv) { int I; Me = get_seqno(); // Adsmith library function, like MPI_Comm_rank() if (Me == 0) { N = atoi(argv[1]); // only node 0 has access to argv, so we need to make the // command-line arguments shared variables, even though they // will never change values after the beginning of the program // the call will allocate a segment of shared memory consisting of // 1 int, with initial value equal to that in N, and point NPtr to it; // its name for reference within the Adsmith system will be "n" NPtr = (int *) adsm_malloc("n",sizeof(int),&N); // have the value of "n" posted to the other nodes adsm_flush(NPtr); NNodes = atoi(argv[2]); NNodesPtr = (int *) adsm_malloc("number of nodes",sizeof(int),&NNodes); adsm_flush(NNodesPtr); } else { // call adsm_malloc() here too, but without initial values, // getting them from node 0 NPtr = (int *) adsm_malloc("n",sizeof(int)); // get the latest value adsm_refresh(NPtr); N = *NPtr; NNodesPtr = (int *) adsm_malloc("number of nodes",sizeof(int)); adsm_refresh(NNodesPtr); NNodes = *NNodesPtr; } if (N % NNodes > 0) { printf("N must be an even multiple of NNodes\n"); exit(1); } // do the same for the shared variable "sum" if (Me == 0) { int Zero = 0; SumPtr = (int *) adsm_malloc("sum",sizeof(int),&Zero); adsm_flush(SumPtr); } else SumPtr = (int *) adsm_malloc("sum",sizeof(int)); // prepare an array of pointers to our array of numbers X = (int **) malloc(N*sizeof(int *)); // there is a function adsm_malloc_array, but stick to the basics char SegName[25]; int Init; for (I = 0; I < N; I++) { sprintf(SegName,"x[%d]",I); if (Me == 0) { Init = I; // make the i-th number = I, just as an example X[I] = (int *) adsm_malloc(SegName,sizeof(int),&Init); adsm_flush(X[I]); } else X[I] = (int *) adsm_malloc(SegName,sizeof(int)); } // node 0 spawns the program at other nodes if (Me == 0) { char *ProgName; // name of the program ProgName = argv[0]; int NSpawned = adsm_spawn(execname(ProgName),NNodes-1); cout<<"number spawned = "<