With this notebook, you will learn
We are going to use Jupyter notebooks in this and other lectures. You provably have worked with notebooks (in Python). If not, here are the basic concepts you need to know to follow the lessons.
To run a Julia Jupyther notebook, open a Julia REPL and type
julia> ]
pkg> add IJulia
julia> using IJulia
julia> notebook()
A new browser window will open. Navigate to the corresponding notebook and open it.
To run a cell, click on a cell and press Shift + Enter. You can also use the "Run" button in the toolbar above.
1+3
4*5
As you can see from the output of previous cell, the value of the last line is displayed. We can suppress the output with a semicolon. Try it. Execute next cell.
1+3
4*5;
Running the two cells below in reverse order won't work (try it).
foo() = "Well done!"
foo()
This is particular to Julia notebooks. You can use package, help, and shell mode just like in the Julia REPL.
] add MPI
? print
; ls
NB. Most of the examples below are taken from the lecture by S.G. Johnson at MIT. See here: https://github.com/mitmath/18S096/blob/master/lectures/lecture1/Boxes-and-registers.ipynb
function sum_hand(a)
s = zero(eltype(a))
for ai in a
s += ai
end
s
end
The Julia macro @test which is provided in the Test package is useful to write (unit) tests in Julia.
using Test
a = rand(5)
@test sum_hand(a) ≈ sum(a)
In Julia, the most straight-forward way of measuring the computation time of a piece of code is with the macro @time.
a = rand(10^7);
@time sum_hand(a)
Note that @time also measures the compile time of a function if it's the first call to that function. So make sure to run @time twice on a freshly compiled function in order to get a more meaningful result.
A part of getting rid of compilation time, one typically wants to measure the runtime several times and compute sole. To do this we can call our code in a for-loop and gather the runtimes using the Julia macro @elapsed. This measures the runtime of an expression in seconds, just as the @time macro, only @elapsed discards the result of the computation and returns the elapsed time instead.
@elapsed sum_hand(a)
The BenchmarkTools extension package provides useful macros for sampling runtimes automatically.
using BenchmarkTools
First of all, the @benchmark macro runs the code multiple times and gives out a lot of details: the minimum and maximum time, mean time, median time, number of samples taken, memory allocations, etc.
bch_sum_hand = @benchmark sum_hand($a)
For quick sanity checks, one can use the @btime macro, which is a convenience wrapper around @benchmark. It returns only the minimum execution time and memory allocations.
@btime sum_hand($a)
Similar to the @elapsed macro, BenchmarkTool's @belapsed discards the return value of the function and instead returns the minimum runtime in seconds.
@belapsed sum_hand($a)
As opposed to @time and @elapsed, @btime and @belapsed run the code several times and return the minimum runtime, thus eliminating possible compilation times from the measurement.
bch_sum = @benchmark sum($a)
using PyCall
py"""
def sum_py_hand(A):
s = 0.0
for a in A:
s += a
return s
"""
sum_py_hand = py"sum_py_hand"
@test sum(a) ≈ sum_py_hand(a)
bch_sum_py_hand = @benchmark sum_py_hand($a)
using Conda
numpy = pyimport("numpy")
sum_numpy = numpy["sum"]
@test sum_numpy(a) ≈ sum(a)
bch_sum_numpy = @benchmark sum_numpy($a)
timings = [bch_sum_hand,bch_sum,bch_sum_py_hand,bch_sum_numpy]
methods = ["sum_hand","sum","sum_py_hand","sum_numpy"]
using DataFrames
df = DataFrame(method=methods,time=timings)
# ✍️ Exercise 3
function sum_hand_fast(a)
s = 0.0
@simd for ai in a
s += ai
end
s
end
@test sum_hand_fast(a) ≈ sum(a)
@benchmark sum_hand_fast($a)
We will look into the third point in a later section of this course.
function sum_hand(a)
s = 0.0
for ai in a
s += ai
end
s
end
using Statistics
a = rand(10^7)
num_it = 15
runtimes = zeros(num_it)
for i in 1:num_it
runtimes[i] = @elapsed sum_hand(a)
end
@show mean(runtimes)
@show std(runtimes)
@show minimum(runtimes)
@show maximum(runtimes);
# ✍️ Exercise 3
function sum_hand_fast(a)
s = 0.0
@simd for ai in a
s += ai
end
s
end