From eae62654d9e1d4076eef9412512e350add38b193 Mon Sep 17 00:00:00 2001 From: Francesc Verdugo Date: Mon, 23 Sep 2024 16:17:55 +0200 Subject: [PATCH] More changes in jacobi_notebook --- docs/src/solutions_for_all_notebooks.md | 126 +++++++++++++++--------- notebooks/jacobi_method.ipynb | 6 +- notebooks/pdes.ipynb | 4 +- 3 files changed, 86 insertions(+), 50 deletions(-) diff --git a/docs/src/solutions_for_all_notebooks.md b/docs/src/solutions_for_all_notebooks.md index 55d1831..1940fdf 100644 --- a/docs/src/solutions_for_all_notebooks.md +++ b/docs/src/solutions_for_all_notebooks.md @@ -292,72 +292,108 @@ end ```julia function jacobi_mpi(n,niters) - comm = MPI.COMM_WORLD - nranks = MPI.Comm_size(comm) + u, u_new = init(n,comm) + load = length(u)-2 rank = MPI.Comm_rank(comm) - if mod(n,nranks) != 0 - println("n must be a multiple of nranks") - MPI.Abort(comm,1) - end - load = div(n,nranks) - u = zeros(load+2) - u[1] = -1 - u[end] = 1 - u_new = copy(u) + nranks = MPI.Comm_size(comm) + nreqs = 2*((rank != 0) + (rank != (nranks-1))) + reqs = MPI.MultiRequest(nreqs) for t in 1:niters - reqs = MPI.Request[] + ireq = 0 if rank != 0 neig_rank = rank-1 - req = MPI.Isend(view(u,2:2),comm,dest=neig_rank,tag=0) - push!(reqs,req) - req = MPI.Irecv!(view(u,1:1),comm,source=neig_rank,tag=0) - push!(reqs,req) + u_snd = view(u,2:2) + u_rcv = view(u,1:1) + dest = neig_rank + source = neig_rank + ireq += 1 + MPI.Isend(u_snd,comm,reqs[ireq];dest) + ireq += 1 + MPI.Irecv!(u_rcv,comm,reqs[ireq];source) end if rank != (nranks-1) neig_rank = rank+1 - s = load+1 - r = load+2 - req = MPI.Isend(view(u,s:s),comm,dest=neig_rank,tag=0) - push!(reqs,req) - req = MPI.Irecv!(view(u,r:r),comm,source=neig_rank,tag=0) - push!(reqs,req) + u_snd = view(u,(load+1):(load+1)) + u_rcv = view(u,(load+2):(load+2)) + dest = neig_rank + source = neig_rank + ireq += 1 + MPI.Isend(u_snd,comm,reqs[ireq];dest) + ireq += 1 + MPI.Irecv!(u_rcv,comm,reqs[ireq];source) end + # Upload interior cells for i in 3:load u_new[i] = 0.5*(u[i-1]+u[i+1]) end + # Wait for the communications to finish MPI.Waitall(reqs) + # Update boundaries for i in (2,load+1) u_new[i] = 0.5*(u[i-1]+u[i+1]) end u, u_new = u_new, u - end - # Gather the results - if rank !=0 - lb = 2 - ub = load+1 - MPI.Send(view(u,lb:ub),comm,dest=0) - u_all = zeros(0) # This will nevel be used - else - u_all = zeros(n+2) - # Set boundary - u_all[1] = -1 - u_all[end] = 1 - # Set data for rank 0 - lb = 2 - ub = load+1 - u_all[lb:ub] = view(u,lb:ub) - # Set data for other ranks - for other_rank in 1:(nranks-1) - lb += load - ub += load - MPI.Recv!(view(u_all,lb:ub),comm;source=other_rank) + return u +end +``` + +### Exercise 2 + +```julia +function jacobi_mpi(n,niters,tol,comm) # new tol arg + u, u_new = init(n,comm) + load = length(u)-2 + rank = MPI.Comm_rank(comm) + nranks = MPI.Comm_size(comm) + nreqs = 2*((rank != 0) + (rank != (nranks-1))) + reqs = MPI.MultiRequest(nreqs) + for t in 1:niters + ireq = 0 + if rank != 0 + neig_rank = rank-1 + u_snd = view(u,2:2) + u_rcv = view(u,1:1) + dest = neig_rank + source = neig_rank + ireq += 1 + MPI.Isend(u_snd,comm,reqs[ireq];dest) + ireq += 1 + MPI.Irecv!(u_rcv,comm,reqs[ireq];source) + end + if rank != (nranks-1) + neig_rank = rank+1 + u_snd = view(u,(load+1):(load+1)) + u_rcv = view(u,(load+2):(load+2)) + dest = neig_rank + source = neig_rank + ireq += 1 + MPI.Isend(u_snd,comm,reqs[ireq];dest) + ireq += 1 + MPI.Irecv!(u_rcv,comm,reqs[ireq];source) end + MPI.Waitall(reqs) + # Compute the max diff in the current + # rank while doing the local update + mydiff = 0.0 + for i in 2:load+1 + u_new[i] = 0.5*(u[i-1]+u[i+1]) + diff_i = abs(u_new[i] - u[i]) + mydiff = max(mydiff,diff_i) + end + # Now we need to find the global diff + diff_ref = Ref(mydiff) + MPI.Allreduce!(diff_ref,max,comm) + diff = diff_ref[] + # If global diff below tol, stop! + if diff < tol + return u_new + end + u, u_new = u_new, u end - return u_all + return u end ``` - diff --git a/notebooks/jacobi_method.ipynb b/notebooks/jacobi_method.ipynb index 258b5b8..d125cc9 100644 --- a/notebooks/jacobi_method.ipynb +++ b/notebooks/jacobi_method.ipynb @@ -281,7 +281,7 @@ "outputs": [], "source": [ "n = 5\n", - "tol = 1e-9\n", + "tol = 1e-10\n", "jacobi_with_tol(n,tol)" ] }, @@ -1531,7 +1531,7 @@ " u = jacobi_mpi(n,niters,comm)\n", " @show u\n", "end\n", - "run(`$(mpiexec()) -np 1 julia --project=. -e $code`);" + "run(`$(mpiexec()) -np 3 julia --project=. -e $code`);" ] }, { @@ -1914,7 +1914,7 @@ "source": [ "### Exercise 2\n", "\n", - "In the parallel implementation of the Jacobi method, we assumed that the method runs for a given number of iterations. In function, `jacobi_with_tol` at the beginning of the notebook shows how the Jacobi iterations can be stopped when the difference between iterations is small. Implement a parallel version of this function. Start with the in Exercise 1 and add the stopping criterion implemented in `jacobi_with_tol`. Use a text editor and the Julia REPL. Do not try to implement the code in a notebook." + "In the parallel implementation of the Jacobi method, we assumed that the method runs for a given number of iterations. In function, `jacobi_with_tol` at the beginning of the notebook shows how the Jacobi iterations can be stopped when the difference between iterations is small. Implement a parallel version of this function. Start with the code in Exercise 1 and add the stopping criterion implemented in `jacobi_with_tol`. Use a text editor and the Julia REPL. Do not try to implement the code in a notebook." ] }, { diff --git a/notebooks/pdes.ipynb b/notebooks/pdes.ipynb index 10f32fc..af4fff4 100644 --- a/notebooks/pdes.ipynb +++ b/notebooks/pdes.ipynb @@ -1534,7 +1534,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Julia 1.9.1", + "display_name": "Julia 1.9.0", "language": "julia", "name": "julia-1.9" }, @@ -1542,7 +1542,7 @@ "file_extension": ".jl", "mimetype": "application/julia", "name": "julia", - "version": "1.9.1" + "version": "1.9.0" } }, "nbformat": 4,