Changes after the lecture on Friday September 15th 2023

This commit is contained in:
Francesc Verdugo 2023-09-15 16:39:05 +02:00
parent 01c69ff310
commit f6a3a677b2
3 changed files with 565 additions and 57 deletions

View File

@ -50,7 +50,6 @@ heatmap(x,y,(i,j)->mandel(i,j,max_iters))
## Asynchronous programming in Julia
### NB2-Q1
Evaluating `compute_π(100_000_000)` takes about 0.25 seconds. Thus, the loop would take about 2.5 seconds since we are calling the function 10 times.
@ -71,4 +70,94 @@ It will take about 3 seconds. The channel has buffer size 4, thus the call to `p
The channel is not buffered and therefore the call to `put!` will block. The cell will run forever, since there is no other task that calls `take!` on this channel.
## Distributed computing in Julia
### NB3-Q1
We send the matrix (16 entries) and then we receive back the result (1 extra integer). Thus, the total number of transferred integers in 17.
### NB3-Q2
Even though we only use a single entry of the matrix in the remote worker, the entire matrix is captured and sent to the worker. Thus, we will transfer 17 integers like in Question 1.
### NB3-Q3
The value of `x` will still be zero since the worker receives a copy of the matrix and it modifies this copy, not the original one.
### NB3-Q4
In this case, the code `a[2]=2` is executed in the main process. Since the matrix is already in the main process, it is not needed to create and send a copy of it. Thus, the code modifies the original matrix and the value of `x` will be 2.
## Distributed computing with MPI
### Exercise 1
```julia
using MPI
MPI.Init()
comm = MPI.Comm_dup(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
```
### Exercise 2
```julia
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
```
This is another possible solution.
```julia
@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)
```

View File

@ -614,6 +614,27 @@
"take!(chnl)"
]
},
{
"cell_type": "markdown",
"id": "ff0da45d",
"metadata": {},
"source": [
"### This will not work!\n",
"\n",
"You really need remote channels to communicate different processes. Standard Channels would not work. For instance, the following code would block at the `take!`. Worker 4 will receive a different copy of the channel and will put values in it. The channel defined in the main process will remain empty and this will make the take! to block. \n",
"\n",
"```julia\n",
"chnl = Channel{Int}()\n",
"@spawnat 4 begin\n",
" for i in 1:5\n",
" put!(chnl,i)\n",
" end\n",
" close(chnl)\n",
"end\n",
"take!(chnl)\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "1b3f8dcc",
@ -769,7 +790,7 @@
"source": [
"\n",
"<div class=\"alert alert-block alert-success\">\n",
"<b>Question (Q1):</b> How many integers are transferred between master and worker? Including both directions. \n",
"<b>Question (NB3-Q1):</b> How many integers are transferred between master and worker? Including both directions. \n",
"</div>\n",
"\n",
"\n",
@ -803,7 +824,7 @@
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<b>Question (Q2):</b> How many integers are transferred between master and worker? Including both directions. \n",
"<b>Question (NB3-Q2):</b> How many integers are transferred between master and worker? Including both directions. \n",
"</div>\n",
"\n",
"\n",
@ -838,7 +859,7 @@
"source": [
"\n",
"<div class=\"alert alert-block alert-success\">\n",
"<b>Question (Q3):</b> Which value will be the value of `x` ? \n",
"<b>Question (NB3-Q3):</b> Which value will be the value of `x` ? \n",
"</div>\n"
]
},
@ -862,7 +883,7 @@
"metadata": {},
"source": [
"<div class=\"alert alert-block alert-success\">\n",
"<b>Question (Q4):</b> Which value will be the value of `x` ? \n",
"<b>Question (NB3-Q4):</b> Which value will be the value of `x` ? \n",
"</div>\n",
"\n",
"Which value will be the value of `x` ?"
@ -1309,7 +1330,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Julia 1.9.3",
"display_name": "Julia 1.9.0",
"language": "julia",
"name": "julia-1.9"
},
@ -1317,7 +1338,7 @@
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "1.9.3"
"version": "1.9.0"
}
},
"nbformat": 4,

File diff suppressed because one or more lines are too long