Information Technology Reference
In-Depth Information
u_prev = (double
*
)malloc((n_p+2)
*
sizeof(double));
u = (double
*
)malloc((n_p+2)
*
sizeof(double));
for (i=0; i<=n_p+1; i++) /
*
enforce initial condition
*
/
u_prev[i] = I((i_start_p+i)
*
dx);
left_neighbor_id = (my_id==0) ? MPI_PROC_NULL : my_id-1;
right_neighbor_id = (my_id==P-1) ? MPI_PROC_NULL : my_id+1;
t=0.;
for (k=1; k<=m; k++) { /
*
time integration loop
*
/
for (i=1; i<=n_p; i++) /
*
computing local inner points
*
/
u[i] = u_prev[i]+alpha
*
(u_prev[i-1]-2
*
u_prev[i]+u_prev[i+1])
+dt
*
f((i_start_p+i)
*
dx,t);
if (my_id==0)
/
*
left physical boundary condition
*
/
u[0] = D0(t+dt);
if (my_id==P-1) /
*
right physical boundary condition
*
/
u[n_p+1] = u_prev[n_p+1]
+2
*
alpha
*
(u_prev[n_p]-u_prev[n_p+1]+N1(t)
*
dx)
+dt
*
f(1,t);
MPI_Sendrecv(&(u[1]),1,MPI_DOUBLE,left_neighbor_id,100,
&(u[n_p+1]),1,MPI_DOUBLE,right_neighbor_id,100,
MPI_COMM_WORLD,&status);
MPI_Sendrecv(&(u[n_p]),1,MPI_DOUBLE,right_neighbor_id,200,
&(u[0]),1,MPI_DOUBLE,left_neighbor_id,200,
MPI_COMM_WORLD,&status);
for (i=0; i<=n_p+1; i++)/
*
date copy before next time step
*
/
u_prev[i] = u[i];
t+=dt;
}
MPI_Finalize();
return 0;
}
We can see that the above code uses a slightly modified Algorithm
10.1
,in
that two calls to the
MPI Sendrecv
function replace two pairs of
MPI Send
and
MPI Recv
. The modified code is thus more compact. A more important motivation
for the modification is to avoid potential communication
deadlocks
, which will arise
if a pair of neighboring processes both start with
MPI Recv
before calling the match-
ing
MPI Send
command. These two MPI processes will be blocked, i.e., none will
be able to return from its
MPI Recv
call, which relies on its neighbor to have issued
the
MPI Send
call. A bullet-proof sequence of
MPI Send
and
MPI Recv
calls is that
process
A
calls
MPI Send
and
MPI Recv
, whereas process
B
calls
MPI Recv
and
MPI Send
.