test different exercise layout - chap 14

This commit is contained in:
Bogumił Kamiński 2022-10-14 12:36:11 +02:00
parent 3b8ffa5d40
commit 6a8b3ae160

View File

@ -14,72 +14,9 @@ average number of items from this set that were drawn at least once.
Call the function running this simulation `boot`.
### Exercise 2
Now write a function `simboot` that takes parameters `n` and `k` and runs
the simulation defined in the `boot` function `k` times. It should return
a named tuple storing `k`, `n`, mean of produced values, and ends of
approximated 95% confidence interval of the result.
Make this function single threaded. Check how long
this function runs for `n=1000` and `k=1_000_000`.
### Exercise 3
Now rewrite this simulator to be multi threaded. Use 4 cores for benchmarking.
Call the function `simbootT`. Check how long this function runs for `n=1000` and
`k=1_000_000`.
### Exercise 4
Now rewrite `boot` and `simbootT` to perform less allocations. Achieve this by
making sure that all allocated objects are passed to `boot` function (so that it
does not do any allocations internally). Call these new functions `boot!` and
`simbootT2`. You might need to use the `Threads.threadid` and `Threads.nthreads`
functions.
### Exercise 5
Use either of the solutions we have developed in the previous exercises to
create a web service taking `k` and `n` parameters and returning the values
produced by `boot` functions and time to run the simulation. You might want to
use the `@timed` macro in your solution.
Start the server.
### Exercise 6
Query the server started in the exercise 5 with
the following parameters:
* `k=1000` and `n=1000`
* `k=1.5` and `n=1000`
### Exercise 7
Collect the data generated by a web service into the `df` data frame for
`k = [10^i for i in 3:6]` and `n = [10^i for i in 1:3]`.
### Exercise 8
Replace the `value` column in the `df` data frame by its contents in-place.
### Exercise 9
Checks that execution time roughly scales proportionally to the product
of `k` times `n`.
### Exercise 10
Plot the expected fraction of seen elements in the set as a function of
`n` by `k` along with 95% confidence interval around these values.
# Solutions
<details>
<summary>Show!</summary>
### Exercise 1
<summary>Solution</summary>
Solution (there are many other approaches you could use):
@ -95,8 +32,22 @@ function boot(n::Integer)
end
```
</details>
### Exercise 2
Now write a function `simboot` that takes parameters `n` and `k` and runs
the simulation defined in the `boot` function `k` times. It should return
a named tuple storing `k`, `n`, mean of produced values, and ends of
approximated 95% confidence interval of the result.
Make this function single threaded. Check how long
this function runs for `n=1000` and `k=1_000_000`.
<details>
<summary>Solution</summary>
Solution:
```
@ -123,8 +74,18 @@ julia> @time simboot(1000, 1_000_000)
We see that on my computer the run time is around 7 seconds.
</details>
### Exercise 3
Now rewrite this simulator to be multi threaded. Use 4 cores for benchmarking.
Call the function `simbootT`. Check how long this function runs for `n=1000` and
`k=1_000_000`.
<details>
<summary>Solution</summary>
Solution:
```
@ -153,8 +114,20 @@ julia> @time simbootT(1000, 1_000_000)
Indeed we see a significant performance improvement.
</details>
### Exercise 4
Now rewrite `boot` and `simbootT` to perform less allocations. Achieve this by
making sure that all allocated objects are passed to `boot` function (so that it
does not do any allocations internally). Call these new functions `boot!` and
`simbootT2`. You might need to use the `Threads.threadid` and `Threads.nthreads`
functions.
<details>
<summary>Solution</summary>
Solution:
```
@ -195,8 +168,21 @@ Indeed, we see that the number of allocations was decreased, which should lower
GC usage. However, the runtime of the simulation is similar since in this task
memory allocation does not account for a significant portion of the runtime.
</details>
### Exercise 5
Use either of the solutions we have developed in the previous exercises to
create a web service taking `k` and `n` parameters and returning the values
produced by `boot` functions and time to run the simulation. You might want to
use the `@timed` macro in your solution.
Start the server.
<details>
<summary>Solution</summary>
Solution (I used the simplest single-threaded code here; this is a complete
code of the web service):
@ -238,8 +224,19 @@ end
Genie.Server.up()
```
</details>
### Exercise 6
Query the server started in the exercise 5 with
the following parameters:
* `k=1000` and `n=1000`
* `k=1.5` and `n=1000`
<details>
<summary>Solution</summary>
Solution:
```
@ -274,8 +271,17 @@ Transfer-Encoding: chunked
As expected we got a positive answer the first time and an error on the second call.
</details>
### Exercise 7
Collect the data generated by a web service into the `df` data frame for
`k = [10^i for i in 3:6]` and `n = [10^i for i in 1:3]`.
<details>
<summary>Solution</summary>
Solution:
```
@ -316,8 +322,16 @@ julia> df
12 │ OK 7.23958 {\n "k": 1000000,\n "n…
```
</details>
### Exercise 8
Replace the `value` column in the `df` data frame by its contents in-place.
<details>
<summary>Solution</summary>
Solution:
```
@ -340,8 +354,17 @@ julia> select!(df, :status, :time, :value => AsTable)
12 │ OK 7.23958 1000000 1000 0.63232 0.632301 0.63234
```
</details>
### Exercise 9
Checks that execution time roughly scales proportionally to the product
of `k` times `n`.
<details>
<summary>Solution</summary>
Solution:
```
@ -366,8 +389,17 @@ single sample stabilizes (for small values the runtime is low so the timing is
more affected by external noise and the other operations that the functions do
affect the results more).
</details>
### Exercise 10
Plot the expected fraction of seen elements in the set as a function of
`n` by `k` along with 95% confidence interval around these values.
<details>
<summary>Solution</summary>
Solution:
```
using Plots