mirror of
https://github.com/fverdugo/XM_40017.git
synced 2025-11-09 00:34:24 +01:00
279 lines
19 KiB
HTML
279 lines
19 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en"><head><meta charset="UTF-8"/><meta name="viewport" content="width=device-width, initial-scale=1.0"/><title>Solutions · XM_40017</title><meta name="title" content="Solutions · XM_40017"/><meta property="og:title" content="Solutions · XM_40017"/><meta property="twitter:title" content="Solutions · XM_40017"/><meta name="description" content="Documentation for XM_40017."/><meta property="og:description" content="Documentation for XM_40017."/><meta property="twitter:description" content="Documentation for XM_40017."/><meta property="og:url" content="https://fverdugo.github.io/XM_40017/solutions_for_all_notebooks/"/><meta property="twitter:url" content="https://fverdugo.github.io/XM_40017/solutions_for_all_notebooks/"/><link rel="canonical" href="https://fverdugo.github.io/XM_40017/solutions_for_all_notebooks/"/><script data-outdated-warner src="../assets/warner.js"></script><link href="https://cdnjs.cloudflare.com/ajax/libs/lato-font/3.0.0/css/lato-font.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/juliamono/0.050/juliamono.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/fontawesome.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/solid.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/brands.min.css" rel="stylesheet" type="text/css"/><link href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.8/katex.min.css" rel="stylesheet" type="text/css"/><script>documenterBaseURL=".."</script><script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" data-main="../assets/documenter.js"></script><script src="../search_index.js"></script><script src="../siteinfo.js"></script><script src="../../versions.js"></script><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/catppuccin-mocha.css" data-theme-name="catppuccin-mocha"/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/catppuccin-macchiato.css" data-theme-name="catppuccin-macchiato"/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/catppuccin-frappe.css" data-theme-name="catppuccin-frappe"/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/catppuccin-latte.css" data-theme-name="catppuccin-latte"/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-dark.css" data-theme-name="documenter-dark" data-theme-primary-dark/><link class="docs-theme-link" rel="stylesheet" type="text/css" href="../assets/themes/documenter-light.css" data-theme-name="documenter-light" data-theme-primary/><script src="../assets/themeswap.js"></script><link href="../assets/favicon.ico" rel="icon" type="image/x-icon"/><script src="../assets/iframeResizer.min.js"></script><link href="../assets/custom.css" rel="stylesheet" type="text/css"/></head><body><div id="documenter"><nav class="docs-sidebar"><a class="docs-logo" href="../"><img src="../assets/logo.png" alt="XM_40017 logo"/></a><div class="docs-package-name"><span class="docs-autofit"><a href="../">XM_40017</a></span></div><button class="docs-search-query input is-rounded is-small is-clickable my-2 mx-auto py-1 px-2" id="documenter-search-query">Search docs (Ctrl + /)</button><ul class="docs-menu"><li><a class="tocitem" href="../">Home</a></li><li><a class="tocitem" href="../getting_started_with_julia/">Getting started</a></li><li><span class="tocitem">Notebooks</span><ul><li><a class="tocitem" href="../julia_basics/">Julia Basics</a></li><li><a class="tocitem" href="../julia_async/">Asynchronous programming in Julia</a></li><li><a class="tocitem" href="../julia_distributed/">Distributed computing in Julia</a></li><li><a class="tocitem" href="../matrix_matrix/">Matrix-matrix multiplication</a></li><li><a class="tocitem" href="../julia_mpi/">MPI (point-to-point)</a></li><li><a class="tocitem" href="../mpi_collectives/">MPI (collectives)</a></li><li><a class="tocitem" href="../jacobi_method/">Jacobi method</a></li></ul></li><li class="is-active"><a class="tocitem" href>Solutions</a><ul class="internal"><li><a class="tocitem" href="#Julia-Basics"><span>Julia Basics</span></a></li><li><a class="tocitem" href="#Asynchronous-programming-in-Julia"><span>Asynchronous programming in Julia</span></a></li><li><a class="tocitem" href="#Distributed-computing-in-Julia"><span>Distributed computing in Julia</span></a></li><li><a class="tocitem" href="#Matrix-matrix-multiplication"><span>Matrix-matrix multiplication</span></a></li><li><a class="tocitem" href="#MPI-(Point-to-point)"><span>MPI (Point-to-point)</span></a></li><li><a class="tocitem" href="#MPI-(collectives)"><span>MPI (collectives)</span></a></li><li><a class="tocitem" href="#Jacobi-method"><span>Jacobi method</span></a></li></ul></li></ul><div class="docs-version-selector field has-addons"><div class="control"><span class="docs-label button is-static is-size-7">Version</span></div><div class="docs-selector control is-expanded"><div class="select is-fullwidth is-size-7"><select id="documenter-version-selector"></select></div></div></div></nav><div class="docs-main"><header class="docs-navbar"><a class="docs-sidebar-button docs-navbar-link fa-solid fa-bars is-hidden-desktop" id="documenter-sidebar-button" href="#"></a><nav class="breadcrumb"><ul class="is-hidden-mobile"><li class="is-active"><a href>Solutions</a></li></ul><ul class="is-hidden-tablet"><li class="is-active"><a href>Solutions</a></li></ul></nav><div class="docs-right"><a class="docs-navbar-link" href="https://github.com/fverdugo/XM_40017/blob/main/docs/src/solutions_for_all_notebooks.md#" title="Edit source on GitHub"><span class="docs-icon fa-solid"></span></a><a class="docs-settings-button docs-navbar-link fa-solid fa-gear" id="documenter-settings-button" href="#" title="Settings"></a><a class="docs-article-toggle-button fa-solid fa-chevron-up" id="documenter-article-toggle-button" href="javascript:;" title="Collapse all docstrings"></a></div></header><article class="content" id="documenter-page"><h1 id="Solutions"><a class="docs-heading-anchor" href="#Solutions">Solutions</a><a id="Solutions-1"></a><a class="docs-heading-anchor-permalink" href="#Solutions" title="Permalink"></a></h1><h2 id="Julia-Basics"><a class="docs-heading-anchor" href="#Julia-Basics">Julia Basics</a><a id="Julia-Basics-1"></a><a class="docs-heading-anchor-permalink" href="#Julia-Basics" title="Permalink"></a></h2><h3 id="Exercise-1"><a class="docs-heading-anchor" href="#Exercise-1">Exercise 1</a><a id="Exercise-1-1"></a><a class="docs-heading-anchor-permalink" href="#Exercise-1" title="Permalink"></a></h3><pre><code class="language-julia hljs">function ex1(a)
|
|
j = 1
|
|
m = a[j]
|
|
for (i,ai) in enumerate(a)
|
|
if m < ai
|
|
m = ai
|
|
j = i
|
|
end
|
|
end
|
|
(m,j)
|
|
end</code></pre><h3 id="Exercise-2"><a class="docs-heading-anchor" href="#Exercise-2">Exercise 2</a><a id="Exercise-2-1"></a><a class="docs-heading-anchor-permalink" href="#Exercise-2" title="Permalink"></a></h3><pre><code class="language-julia hljs">ex2(f,g) = x -> f(x) + g(x)</code></pre><h3 id="Exercise-3"><a class="docs-heading-anchor" href="#Exercise-3">Exercise 3</a><a id="Exercise-3-1"></a><a class="docs-heading-anchor-permalink" href="#Exercise-3" title="Permalink"></a></h3><pre><code class="language-julia hljs">using GLMakie
|
|
max_iters = 100
|
|
n = 1000
|
|
x = LinRange(-1.7,0.7,n)
|
|
y = LinRange(-1.2,1.2,n)
|
|
heatmap(x,y,(i,j)->mandel(i,j,max_iters))</code></pre><h2 id="Asynchronous-programming-in-Julia"><a class="docs-heading-anchor" href="#Asynchronous-programming-in-Julia">Asynchronous programming in Julia</a><a id="Asynchronous-programming-in-Julia-1"></a><a class="docs-heading-anchor-permalink" href="#Asynchronous-programming-in-Julia" title="Permalink"></a></h2><h2 id="Distributed-computing-in-Julia"><a class="docs-heading-anchor" href="#Distributed-computing-in-Julia">Distributed computing in Julia</a><a id="Distributed-computing-in-Julia-1"></a><a class="docs-heading-anchor-permalink" href="#Distributed-computing-in-Julia" title="Permalink"></a></h2><h3 id="Exercise-1-2"><a class="docs-heading-anchor" href="#Exercise-1-2">Exercise 1</a><a class="docs-heading-anchor-permalink" href="#Exercise-1-2" title="Permalink"></a></h3><pre><code class="language-julia hljs">f = () -> Channel{Int}(1)
|
|
chnls = [ RemoteChannel(f,w) for w in workers() ]
|
|
@sync for (iw,w) in enumerate(workers())
|
|
@spawnat w begin
|
|
chnl_snd = chnls[iw]
|
|
if w == 2
|
|
chnl_rcv = chnls[end]
|
|
msg = 2
|
|
println("msg = $msg")
|
|
put!(chnl_snd,msg)
|
|
msg = take!(chnl_rcv)
|
|
println("msg = $msg")
|
|
else
|
|
chnl_rcv = chnls[iw-1]
|
|
msg = take!(chnl_rcv)
|
|
msg += 1
|
|
println("msg = $msg")
|
|
put!(chnl_snd,msg)
|
|
end
|
|
end
|
|
end</code></pre><p>This is another possible solution.</p><pre><code class="language-julia hljs">@everywhere function work(msg)
|
|
println("msg = $msg")
|
|
if myid() != nprocs()
|
|
next = myid() + 1
|
|
@fetchfrom next work(msg+1)
|
|
else
|
|
@fetchfrom 2 println("msg = $msg")
|
|
end
|
|
end
|
|
msg = 2
|
|
@fetchfrom 2 work(msg)</code></pre><h2 id="Matrix-matrix-multiplication"><a class="docs-heading-anchor" href="#Matrix-matrix-multiplication">Matrix-matrix multiplication</a><a id="Matrix-matrix-multiplication-1"></a><a class="docs-heading-anchor-permalink" href="#Matrix-matrix-multiplication" title="Permalink"></a></h2><h3 id="Exercise-1-3"><a class="docs-heading-anchor" href="#Exercise-1-3">Exercise 1</a><a class="docs-heading-anchor-permalink" href="#Exercise-1-3" title="Permalink"></a></h3><pre><code class="language-julia hljs">function matmul_dist_3!(C,A,B)
|
|
m = size(C,1)
|
|
n = size(C,2)
|
|
l = size(A,2)
|
|
@assert size(A,1) == m
|
|
@assert size(B,2) == n
|
|
@assert size(B,1) == l
|
|
@assert mod(m,nworkers()) == 0
|
|
nrows_w = div(m,nworkers())
|
|
@sync for (iw,w) in enumerate(workers())
|
|
lb = 1 + (iw-1)*nrows_w
|
|
ub = iw*nrows_w
|
|
A_w = A[lb:ub,:]
|
|
ftr = @spawnat w begin
|
|
C_w = similar(A_w)
|
|
matmul_seq!(C_w,A_w,B)
|
|
C_w
|
|
end
|
|
@async C[lb:ub,:] = fetch(ftr)
|
|
end
|
|
C
|
|
end
|
|
|
|
@everywhere function matmul_seq!(C,A,B)
|
|
m = size(C,1)
|
|
n = size(C,2)
|
|
l = size(A,2)
|
|
@assert size(A,1) == m
|
|
@assert size(B,2) == n
|
|
@assert size(B,1) == l
|
|
z = zero(eltype(C))
|
|
for j in 1:n
|
|
for i in 1:m
|
|
Cij = z
|
|
for k in 1:l
|
|
@inbounds Cij = Cij + A[i,k]*B[k,j]
|
|
end
|
|
C[i,j] = Cij
|
|
end
|
|
end
|
|
C
|
|
end</code></pre><h2 id="MPI-(Point-to-point)"><a class="docs-heading-anchor" href="#MPI-(Point-to-point)">MPI (Point-to-point)</a><a id="MPI-(Point-to-point)-1"></a><a class="docs-heading-anchor-permalink" href="#MPI-(Point-to-point)" title="Permalink"></a></h2><h3 id="Exercise-1-4"><a class="docs-heading-anchor" href="#Exercise-1-4">Exercise 1</a><a class="docs-heading-anchor-permalink" href="#Exercise-1-4" title="Permalink"></a></h3><pre><code class="language-julia hljs">function matmul_mpi_3!(C,A,B)
|
|
comm = MPI.COMM_WORLD
|
|
rank = MPI.Comm_rank(comm)
|
|
P = MPI.Comm_size(comm)
|
|
if rank == 0
|
|
N = size(A,1)
|
|
myB = B
|
|
for dest in 1:(P-1)
|
|
MPI.Send(B,comm;dest)
|
|
end
|
|
else
|
|
source = 0
|
|
status = MPI.Probe(comm,MPI.Status;source)
|
|
count = MPI.Get_count(status,eltype(B))
|
|
N = Int(sqrt(count))
|
|
myB = zeros(N,N)
|
|
MPI.Recv!(myB,comm;source)
|
|
end
|
|
L = div(N,P)
|
|
myA = zeros(L,N)
|
|
if rank == 0
|
|
lb = L*rank+1
|
|
ub = L*(rank+1)
|
|
myA[:,:] = view(A,lb:ub,:)
|
|
for dest in 1:(P-1)
|
|
lb = L*dest+1
|
|
ub = L*(dest+1)
|
|
MPI.Send(view(A,lb:ub,:),comm;dest)
|
|
end
|
|
else
|
|
source = 0
|
|
MPI.Recv!(myA,comm;source)
|
|
end
|
|
myC = myA*myB
|
|
if rank == 0
|
|
lb = L*rank+1
|
|
ub = L*(rank+1)
|
|
C[lb:ub,:] = myC
|
|
for source in 1:(P-1)
|
|
lb = L*source+1
|
|
ub = L*(source+1)
|
|
MPI.Recv!(view(C,lb:ub,:),comm;source)
|
|
end
|
|
else
|
|
dest = 0
|
|
MPI.Send(myC,comm;dest)
|
|
end
|
|
C
|
|
end</code></pre><h3 id="Exercise-2-2"><a class="docs-heading-anchor" href="#Exercise-2-2">Exercise 2</a><a class="docs-heading-anchor-permalink" href="#Exercise-2-2" title="Permalink"></a></h3><pre><code class="language-julia hljs">using MPI
|
|
MPI.Init()
|
|
comm = MPI.COMM_WORLD
|
|
rank = MPI.Comm_rank(comm)
|
|
nranks = MPI.Comm_size(comm)
|
|
buffer = Ref(0)
|
|
if rank == 0
|
|
msg = 2
|
|
buffer[] = msg
|
|
println("msg = $(buffer[])")
|
|
MPI.Send(buffer,comm;dest=rank+1,tag=0)
|
|
MPI.Recv!(buffer,comm;source=nranks-1,tag=0)
|
|
println("msg = $(buffer[])")
|
|
else
|
|
dest = if (rank != nranks-1)
|
|
rank+1
|
|
else
|
|
0
|
|
end
|
|
MPI.Recv!(buffer,comm;source=rank-1,tag=0)
|
|
buffer[] += 1
|
|
println("msg = $(buffer[])")
|
|
MPI.Send(buffer,comm;dest,tag=0)
|
|
end</code></pre><h2 id="MPI-(collectives)"><a class="docs-heading-anchor" href="#MPI-(collectives)">MPI (collectives)</a><a id="MPI-(collectives)-1"></a><a class="docs-heading-anchor-permalink" href="#MPI-(collectives)" title="Permalink"></a></h2><h3 id="Exercise-1-5"><a class="docs-heading-anchor" href="#Exercise-1-5">Exercise 1</a><a class="docs-heading-anchor-permalink" href="#Exercise-1-5" title="Permalink"></a></h3><pre><code class="language-julia hljs">function matmul_mpi_3!(C,A,B)
|
|
comm = MPI.COMM_WORLD
|
|
rank = MPI.Comm_rank(comm)
|
|
P = MPI.Comm_size(comm)
|
|
root = 0
|
|
if rank == root
|
|
N = size(A,1)
|
|
Nref = Ref(N)
|
|
else
|
|
Nref = Ref(0)
|
|
end
|
|
MPI.Bcast!(Nref,comm;root)
|
|
N = Nref[]
|
|
if rank == root
|
|
myB = B
|
|
else
|
|
myB = zeros(N,N)
|
|
end
|
|
MPI.Bcast!(myB,comm;root)
|
|
L = div(N,P)
|
|
# Tricky part
|
|
# Julia works "col major"
|
|
myAt = zeros(N,L)
|
|
At = collect(transpose(A))
|
|
MPI.Scatter!(At,myAt,comm;root)
|
|
myCt = transpose(myB)*myAt
|
|
Ct = similar(C)
|
|
MPI.Gather!(myCt,Ct,comm;root)
|
|
C .= transpose(Ct)
|
|
C
|
|
end</code></pre><p>This other solution uses a column partition instead of a row partition. It is more natural to work with column partitions in Julia if possible since matrices are in "col major" format. Note that we do not need all the auxiliary transposes anymore.</p><pre><code class="language-julia hljs">function matmul_mpi_3!(C,A,B)
|
|
comm = MPI.COMM_WORLD
|
|
rank = MPI.Comm_rank(comm)
|
|
P = MPI.Comm_size(comm)
|
|
root = 0
|
|
if rank == root
|
|
N = size(A,1)
|
|
Nref = Ref(N)
|
|
else
|
|
Nref = Ref(0)
|
|
end
|
|
MPI.Bcast!(Nref,comm;root)
|
|
N = Nref[]
|
|
if rank == root
|
|
myA = A
|
|
else
|
|
myA = zeros(N,N)
|
|
end
|
|
MPI.Bcast!(myA,comm;root)
|
|
L = div(N,P)
|
|
myB = zeros(N,L)
|
|
MPI.Scatter!(B,myB,comm;root)
|
|
myC = myA*myB
|
|
MPI.Gather!(myC,C,comm;root)
|
|
C
|
|
end</code></pre><h2 id="Jacobi-method"><a class="docs-heading-anchor" href="#Jacobi-method">Jacobi method</a><a id="Jacobi-method-1"></a><a class="docs-heading-anchor-permalink" href="#Jacobi-method" title="Permalink"></a></h2><h3 id="Exercise-1-6"><a class="docs-heading-anchor" href="#Exercise-1-6">Exercise 1</a><a class="docs-heading-anchor-permalink" href="#Exercise-1-6" title="Permalink"></a></h3><pre><code class="language-julia hljs">function jacobi_mpi(n,niters)
|
|
comm = MPI.COMM_WORLD
|
|
nranks = MPI.Comm_size(comm)
|
|
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)
|
|
for t in 1:niters
|
|
reqs = MPI.Request[]
|
|
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)
|
|
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)
|
|
end
|
|
for i in 3:load
|
|
u_new[i] = 0.5*(u[i-1]+u[i+1])
|
|
end
|
|
MPI.Waitall(reqs)
|
|
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)
|
|
end
|
|
end
|
|
return u_all
|
|
end</code></pre></article><nav class="docs-footer"><a class="docs-footer-prevpage" href="../jacobi_method/">« Jacobi method</a><div class="flexbox-break"></div><p class="footer-message">Powered by <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> and the <a href="https://julialang.org/">Julia Programming Language</a>.</p></nav></div><div class="modal" id="documenter-settings"><div class="modal-background"></div><div class="modal-card"><header class="modal-card-head"><p class="modal-card-title">Settings</p><button class="delete"></button></header><section class="modal-card-body"><p><label class="label">Theme</label><div class="select"><select id="documenter-themepicker"><option value="auto">Automatic (OS)</option><option value="documenter-light">documenter-light</option><option value="documenter-dark">documenter-dark</option><option value="catppuccin-latte">catppuccin-latte</option><option value="catppuccin-frappe">catppuccin-frappe</option><option value="catppuccin-macchiato">catppuccin-macchiato</option><option value="catppuccin-mocha">catppuccin-mocha</option></select></div></p><hr/><p>This document was generated with <a href="https://github.com/JuliaDocs/Documenter.jl">Documenter.jl</a> version 1.7.0 on <span class="colophon-date" title="Thursday 12 September 2024 16:06">Thursday 12 September 2024</span>. Using Julia version 1.10.5.</p></section><footer class="modal-card-foot"></footer></div></div></div></body></html>
|