global size int N = 8 # grid dimension int PR = 2 # number of processes int S # strip size body size getarg(1, N); getarg(2, PR); S = N/PR if ((N mod PR) != 0) { write("N must be a multiple of PR"); stop(1) } end global data import size real grid[2][0:N+1,0:N+1] real epsilon = 0.3 int nxt = 2 int cur = 1 op print() body data grid = ([2] ([N+2] ([N+2] 0.0))) real l= 1.0 real t=2.1 real r=3.3 real b=4.9 for [ i = 0 to N+1 ] { grid[cur][i,0] = l; grid[nxt][i,0] = l } for [ i = 0 to N+1 ] { grid[cur][0,i] = t; grid[nxt][0,i] = t } for [ i = 0 to N+1 ] { grid[cur][i,N+1] = r; grid[nxt][i,N+1] = r } for [ i = 0 to N+1 ] { grid[cur][N+1,i] = b; grid[nxt][N+1,i] = b } proc print() { write() for [ i = 1 to N ] { for [ j = 1 to N ] { printf("%5.3f ",grid[cur][i,j]) } write() } } end global barrier_synch import size op barrier() body barrier_synch int cnt = 0 int sleep = 1 sem mutex = 1, delay[1:2] = ([2] 0) proc barrier() { P(mutex) cnt++ if (cnt < PR) { int mysleep = sleep V(mutex); P(delay[mysleep]) } else { cnt = 0 for [ i = 1 to PR-1 ] { V(delay[sleep]) } sleep = 3-sleep # use other delay semaphore V(mutex) } } end resource jacobi() import data, size, barrier_synch real maxdiff[1:PR] # differences int iters = 0 process strip [ p = 1 to PR ] { const int r = (p-1)*S + 1 # starting row of strip real mdiff while (true) { # if process 1, count iterations if (p == 1) { iters++ } # compute new values for strip of grid # use local variable to hold maximum difference mdiff = 0.0 for [ i = r to r+S-1, j = 1 to N ] { grid[nxt][i,j] = (grid[cur][i-1,j] + grid[cur][i,j-1] + \ grid[cur][i+1,j] + grid[cur][i,j+1]) / 4 mdiff = max(mdiff, abs(grid[nxt][i,j] - grid[cur][i,j])) } maxdiff[p] = mdiff # store mdiff in shared array barrier() # if process 1, swap roles of grids if (p == 1) { nxt :=: cur } # check for convergence and possibly terminate for [ i = 1 to PR ] { mdiff = max(mdiff, maxdiff[i]) } if (mdiff <= epsilon) { exit } barrier() } } final { write("convergence after", iters, "iterations") print() } end