mirror of
https://github.com/fverdugo/XM_40017.git
synced 2025-11-09 00:24:25 +01:00
Adding solutions to exercises
This commit is contained in:
parent
dc2f65480f
commit
4ad26425f6
@ -123,8 +123,8 @@ makedocs(;
|
||||
"Matrix-matrix multiplication"=>"matrix_matrix.md",
|
||||
"Jacobi method" => "jacobi_method.md",
|
||||
"All pairs of shortest paths" => "asp.md",
|
||||
# "Solutions" => "solutions.md",
|
||||
],
|
||||
"Solutions" => "solutions_for_all_notebooks.md",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
74
docs/src/solutions_for_all_notebooks.md
Normal file
74
docs/src/solutions_for_all_notebooks.md
Normal file
@ -0,0 +1,74 @@
|
||||
# Solutions
|
||||
|
||||
## Julia Basics
|
||||
|
||||
### NB1-Q1
|
||||
|
||||
In the first, line we assign a variable to a value. In the second line, we assign another variable to the same value. Thus,we have 2 variables associated with the same value. In line 3, we associate `y` to a new value (re-assignment). Thus, we have 2 variables associated with 2 different values. Variable `x` is still associated with its original value. Thus, the value at the final line is `x=1`.
|
||||
|
||||
### NB1-Q2
|
||||
|
||||
It will be `1` for very similar reasons as in the previous questions: we are reassigning a local variable, not the global variable defined outside the function.
|
||||
|
||||
### NB1-Q3
|
||||
|
||||
It will be `6`. In the returned function `f2`, `x` is equal to `2`. Thus, when calling `f2(3)` we compute `2*3`.
|
||||
|
||||
|
||||
### Exercise 1
|
||||
|
||||
```julia
|
||||
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
|
||||
```
|
||||
|
||||
### Exercise 2
|
||||
|
||||
```julia
|
||||
ex2(f,g) = x -> f(x) + g(x)
|
||||
```
|
||||
|
||||
### Exercise 3
|
||||
|
||||
```julia
|
||||
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))
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
### NB2-Q2
|
||||
|
||||
The time in doing the loop will be almost zero since the loop just schedules 10 tasks, which should be very fast.
|
||||
|
||||
### NB2-Q3
|
||||
|
||||
It will take 2.5 seconds, like in question 1. The `@sync` macro forces to wait for all tasks we have generated with the `@async` macro. Since we have created 10 tasks and each of them takes about 0.25 seconds, the total time will be about 2.5 seconds.
|
||||
|
||||
### NB2-Q4
|
||||
|
||||
It will take about 3 seconds. The channel has buffer size 4, thus the call to `put!`will not block. The call to `take!` will not block neither since there is a value stored in the channel. The taken value is 3 and therefore we will wait for 3 seconds.
|
||||
|
||||
### NB2-Q5
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"\n",
|
||||
"### Creating a task\n",
|
||||
"\n",
|
||||
"A task is a piece of computation work that can be run asynchronously (i.e., that can be run in the background). To create a task, we first need to create a function that represents the work to be done in the task. In next cell, we generate a task that generates and sums two matrices."
|
||||
"Technically, a task in Julia is a *symmetric co-routine*. More informally, a task is a piece of computation work that can be started (scheduled) at some point in the future, and that can be interrupted and resumed. To create a task, we first need to create a function that represents the work to be done in the task. In next cell, we generate a task that generates and sums two matrices."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -181,7 +181,7 @@
|
||||
"source": [
|
||||
"### Tasks do not run in parallel\n",
|
||||
"\n",
|
||||
"It is also important to note that tasks do not run in parallel. We were able to run code while previous tasks was running because the task was idling most of the time. If the task does actual work, the current process will be busy running this task and it is likely that we cannot run other code at the same time. Let's illustrate this with an example. The following code computes an approximation of $\\pi$ using [Leibniz formula](https://en.wikipedia.org/wiki/Leibniz_formula_for_pi). The quality of the approximation increases with the value of `n`."
|
||||
"It is also important to note that tasks do not run in parallel. We were able to run code while previous tasks was running because the task was idling most of the time in the sleep function. If the task does actual work, the current process will be busy running this task and preventing to run other tasks. Let's illustrate this with an example. The following code computes an approximation of $\\pi$ using [Leibniz formula](https://en.wikipedia.org/wiki/Leibniz_formula_for_pi). The quality of the approximation increases with the value of `n`."
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -265,6 +265,109 @@
|
||||
"1+1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "a700fe69",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### `yield`\n",
|
||||
"\n",
|
||||
"If tasks do not run in parallel, what is the purpose of tasks? Tasks are handy since they can be interrupted and to switch control to other tasks. This is achieved via function `yield`. When we call yield, we provide the opportunity to switch to another task. The function below is a variation of function `compute_π` in which we yield every 1000 iterations. At the call to yield we allow other tasks to take over. Without this call to yield, once we start function `compute_π` we cannot start any other tasks until this function finishes."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9260c065",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"function compute_π_yield(n)\n",
|
||||
" s = 1.0\n",
|
||||
" for i in 1:n\n",
|
||||
" s += (isodd(i) ? -1 : 1) / (i*2+1)\n",
|
||||
" if mod(i,1000) == 0\n",
|
||||
" yield()\n",
|
||||
" end\n",
|
||||
" end\n",
|
||||
" 4*s\n",
|
||||
"end"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "69fd4131",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can check this behavior experimentally with the two following cells. The next one creates and schedules a task that computes pi with the function `compute_π_yield`. Note that you can run the 2nd cell bellow while this task is running since we call to yield often inside `compute_π_yield`."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "a85f3f39",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fun = () -> compute_π_yield(3_000_000_000)\n",
|
||||
"t = Task(fun)\n",
|
||||
"schedule(t)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "24e23e88",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"1+1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "66ca10d6",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"### Example: Implementing function sleep\n",
|
||||
"\n",
|
||||
"Using yield, we can implement our own version of the sleep function as follows:"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "beed2b29",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"function mysleep(secs)\n",
|
||||
" final_time = time() + secs\n",
|
||||
" while time() < final_time\n",
|
||||
" yield()\n",
|
||||
" end\n",
|
||||
" nothing\n",
|
||||
"end"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "5c44f6c1",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"You can check that it behaves as expected."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "73c13bfb",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"@time mysleep(3)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"id": "25048665",
|
||||
@ -602,7 +705,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question (Q1):</b> How long will the compute time of next cell be? \n",
|
||||
"<b>Question (NB2-Q1):</b> How long will the compute time of next cell be? \n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
" a) 10*t\n",
|
||||
@ -629,7 +732,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question (Q2):</b> How long will the compute time of next cell be? \n",
|
||||
"<b>Question (NB2-Q2):</b> How long will the compute time of next cell be? \n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
" a) 10*t\n",
|
||||
@ -657,7 +760,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question (Q3):</b> How long will the compute time of next cell be? \n",
|
||||
"<b>Question (NB2-Q3):</b> How long will the compute time of next cell be? \n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
" a) 10*t\n",
|
||||
@ -684,7 +787,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question (Q4):</b> How long will the compute time of the 2nd cell be? \n",
|
||||
"<b>Question (NB2-Q4):</b> How long will the compute time of the 2nd cell be? \n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
" a) infinity\n",
|
||||
@ -724,7 +827,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question (Q5):</b> How long will the compute time of the 2nd cell be? \n",
|
||||
"<b>Question (NB2-Q5):</b> How long will the compute time of the 2nd cell be? \n",
|
||||
"</div>\n",
|
||||
"\n",
|
||||
" a) infinity\n",
|
||||
|
||||
@ -449,7 +449,7 @@
|
||||
"source": [
|
||||
"\n",
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> What will be the value of `x` in the last line ? (Think your answer before executing next cell to find out the result) \n",
|
||||
"<b>Question (NB1-Q1):</b> What will be the value of `x` in the last line ? (Think your answer before executing next cell to find out the result) \n",
|
||||
"</div>\n",
|
||||
"\n"
|
||||
]
|
||||
@ -557,7 +557,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> What will be the value of `x` in the last line ?\n",
|
||||
"<b>Question (NB1-Q2):</b> What will be the value of `x` in the last line ?\n",
|
||||
"</div>\n"
|
||||
]
|
||||
},
|
||||
@ -1030,7 +1030,7 @@
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"<div class=\"alert alert-block alert-success\">\n",
|
||||
"<b>Question:</b> Which will be the value of `x` below? \n",
|
||||
"<b>Question (NB1-Q3):</b> Which will be the value of `x` below? \n",
|
||||
"</div>\n",
|
||||
"\n"
|
||||
]
|
||||
@ -1645,14 +1645,6 @@
|
||||
"\n",
|
||||
"This notebook is part of the course [Programming Large Scale Parallel Systems](https://www.francescverdugo.com/XM_40017/) at Vrije Universiteit Amsterdam and may be used under a [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) license."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "f8d92f25",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user