Skip to content
Snippets Groups Projects
Commit 47aefccf authored by Miroslav Kratochvil's avatar Miroslav Kratochvil :bicyclist:
Browse files

fix review, add magicks

parent 5f90fbe1
No related branches found
No related tags found
No related merge requests found
<div class=leader>
Bootstrapping Julia
🪓🪚🪛🔧🔨<br>
Bootstrapping Julia
</div>
......@@ -63,20 +64,8 @@ include("mylibrary.jl")
- Load a package, add its exports to the global namespace
using UnicodePlots
- Load a package without exports
```julia
import UnicodePlots
```
- Trick: load package exports to a custom namespace
```julia
module Plt
using UnicodePlots
end
using UnicodePlots
```
......@@ -95,69 +84,68 @@ end
] remove UnicodePlots
```
- Enter a local project with separate package versions
```julia
] activate path/to/project
```
- Install dependencies of the local project
# 💡 How to write a standalone program?
*Your scripts should communicate well with the environment!*
(that means, among other, you)
```julia
] instantiate
```
#!/usr/bin/env julia
(Project data is stored in `Project.toml`, `Manifest.toml`)
function process_file(filename)
@info "Processing $filename..."
# ... do something ...
if error_detected
@error "something terrible has happened"
exit(1)
end
end
# Workflow: Testing in REPL
for file in ARGS
process_file(file)
end
```
- Code in REPL
- Paste pieces of code back and forth to editor/IDE
- VS Code etc.: `Ctrl`+`Enter`
- Linuxes: magic middleclick
- A script is eventually materialized
- ...or picked from history in `.julia/logs/` :)
Correct processing of commandline arguments makes your scripts *repurposable*
and *configurable*.
# Workflow: Write a good standalone script
*Your scripts should communicate well with the environment!* (that means, among other, you)
# 💡 Workflow: Make a local environment for your script
```julia
#!/usr/bin/env julia
global_param = get(ENV, "MY_SETTING", "default")
- Enter a local project with separate package versions
function process_file(fn::String)
println("working on $fn...")
#...
if error_detected
@error "something terrible has happened" fn
exit(1)
end
end
```julia
] activate path/to/project
```
process_file.(ARGS)
exit(0)
- Install dependencies of the local project
```julia
] instantiate
```
- Execute a script with the project environment
```sh
$ julia --project=path/to/project script.jl
```
# Workflow: What makes your script sustainable?
(Project data is stored in `Project.toml`, `Manifest.toml`.)
Main UNIX facilities:
- Commandline arguments tell the script where to do the work (make it *repurposable*)
- Environment lets you customize stuff that doesn't easily fit into arguments (makes it *reconfigurable*)
- Proper success & error reporting tells the other programs that something broke (makes the pipeline *robust*)
- `#!` (aka "shabang") converts your script to a normal program (makes the user (you) much happier)
<div class=leader>
PAUSE
☕🧋🧃<br>
PAUSE
</div>
Let's have *10 minutes* for a coffee or something.
......
<div class=leader>
Parallel Julia on HPCs
🚀🚀🚀<br>
Parallel Julia
</div>
......@@ -13,16 +14,6 @@
# What does ULHPC look like?
<center>
<img src="slides/img/iris.png" width="30%">
<br>
<tt>hpc-docs.uni.lu/systems/iris</tt>
</center>
# Basic parallel processing
**Using `Threads`:**
......@@ -42,34 +33,93 @@ end
```julia
using Distributed
addprocs(N)
newVector = pmap(function, oldVector)
newVector = pmap(myFunction, myVector)
```
We will use the `Distributed` approach.
# Managing your workers
```julia
using Distributed
addprocs(4)
myid()
workers()
```
Running commands on workers:
```julia
@spawnat 3 @info "Message from worker"
@spawnat :any myid()
```
Getting results from workers:
```julia
job = @spawnat :any begin sleep(10); return 123+321; end
fetch(job)
```
Cleaning up:
```julia
rmprocs(workers())
```
# Processing lots of data items in parallel
```julia
datafiles = ["file$i.csv" for i=1:20]
@everywhere function process_file(name)
println("Processing file $name")
# ... do something ...
end
@sync for f in datafiles
@async @spawnat :any process_file(f)
end
```
# Gathering results from workers
```julia
items = collect(1:1000)
@everywhere compute_item(i) = 123 + 321*i
pmap(compute_item, items)
```
💡💡💡 Doing manually with `@spawnat`:
```julia
futures = [@spawnat :any compute_item(item) for item in items]
fetch.(futures)
```
# How to design for parallelization?
- *Divide software into completely independent parts*
- avoid shared writeable state (to allow reentrancy)
- avoid global variables (to allow separation from the "mother" process)
- avoid complicated intexing in arrays (to allow slicing)
- avoid tiny computation steps (to allow high-yield computation)
- *Design for utilization of the high-level looping primitives*
- use `map`
- use `reduce` or `mapreduce`
- parallelize programs using `pmap` and `dmapreduce` (DistributedData.jl)
- Decompose more advanced programs into *tasks with dependencies*
- Dagger.jl
- `make -jN` may be a surprisingly good tool for parallelization!
**Recommended way:** *Utilize the high-level looping primitives!*
- use `map`, parallelize by just switching to `pmap`
- use `reduce` or `mapreduce`, parallelize by just switching to `dmapreduce` (DistributedData.jl)
# Parallel → distributed processing
# 💡 Parallel → distributed processing
You need a working `ssh`
connection to the server, ideally with keys:
It is very easy to organize *multiple computers* to work for you!
You need a working `ssh` connection:
```sh
user@pc1 $ ssh server1
......@@ -88,9 +138,26 @@ julia> addprocs([("server1", 10), ("pc2", 2)])
# Making a HPC-compatible script
<div class=leader>
💻 🇱🇺 🧮 💿<br>
Utilizing ULHPC 💡
</div>
# What does ULHPC look like?
<center>
<img src="slides/img/iris.png" width="30%">
<br>
<tt>hpc-docs.uni.lu/systems/iris</tt>
</center>
# Making a HPC-compatible Julia script
Main problems:
Main challenges:
1. discover the available resources
2. spawn worker processes at the right place
......@@ -128,7 +195,8 @@ You start the script using:
<div class=leader>
Questions?
🫐 🍎 🍈 🍇<br>
Questions?
</div>
Lets do some hands-on problem solving (expected around 15 minutes)
2022/2022-06-08_JuliaForNewcomers/slides/img/whyjulia.png

2.32 MiB

......@@ -25,6 +25,6 @@
.reveal pre code {border: 0; font-size: 18pt; line-height:27pt;}
em {color: #e02;}
li {margin-bottom: 1ex;}
div.leader {font-size:400%; font-weight:bold; margin: 1em;}
div.leader {font-size:400%; line-height:120%; font-weight:bold; margin: 1em;}
section {padding-bottom: 10em;}
</style>
......@@ -10,27 +10,12 @@
*Is Julia ecosystem ready for my needs?*
- Likely. If not, extending the packages is unbelievably easy.
- Likely. If not, extending the packages is super easy.
- Base includes most of the functionality of Matlab, R and Python with numpy,
and many useful bits of C++
# How to lose performance?
# Why Julia?
Type `a+1` in a typical interpreted language.
Computer has to do this:
1. Check if `a` exists in the available variables
2. Find the address of `a`
3. Check if `a` is an actual object or null
4. Find if there is `__add__` in the object, get its address
5. Find if `__add__` is a function with 2 parameters
6. Load the value of `a`
7. Call the function, push call stack
8. Find if 1 is an integer and can be added
9. Check if `a` has a primitive representation (ie. not a big-int)
10. Run the `add` instruction (this takes 1 CPU cycle!)
11. Pop call stack
12. Save the result to the place where the runtime can work with it
<center><img src="slides/img/whyjulia.png" width="80%"></center>
<div class=leader>
Working with data
📘 💽 📈<br>
Working with data
</div>
......@@ -139,16 +140,18 @@ DataFrame(XLSX.gettable(x["Results sheet"])...)
# Plotting
<center>
<img src="slides/img/unicodeplot.png" height="80%" />
<img src="slides/img/unicodeplot.png" width="40%" />
</center>
# Usual plotting packages
- `UnicodePlots.jl` (useful in terminal)
- `Plots.jl` (matplotlib workalike)
- `UnicodePlots.jl` (useful in terminal, https://github.com/JuliaPlots/UnicodePlots.jl)
- `Plots.jl` (matplotlib workalike, works with Plotly)
- `GLMakie.jl` (interactive plots)
- `CairoMakie` (PDF export of Makie plots)
- `CairoMakie.jl` (PDF export of Makie plots)
Native `ggplot` and `cowplot` ports are in development.
Gallery available: https://makie.juliaplots.org
<div class=leader>
Julia language primer
🔵 🔴 🟢 🟣<br>
Julia language primer
</div>
......@@ -39,7 +40,7 @@ false, true
- `Vector{Int}`
```julia
1, 2, 5, 10
[1, 2, 5, 10]
```
- `Matrix{Float64}`
......@@ -61,35 +62,6 @@ false, true
# Supertype hierarchy
Types possess a single supertype, which allows you to easily group
multiple types under e.g. `Real`, `Function`, `Type`, `Any`, ...
<pre style="font-size: 90%; line-height:120%;"><code class="language-julia hljs">
julia> Int
Int64
julia> Int.super
Signed
julia> Int.super.super
Integer
julia> Int.super.super.super
Real
julia> Int.super.super.super.super
Number
julia> Int.super.super.super.super.super
Any
</code></pre>
Useful for restricting your functions to work on reasonable subsets of inputs.
# Basic functionality and expectable stuff
- Math: `+`, `-`, `*`, `/`, `^`, ...
......@@ -139,18 +111,20 @@ else # optional
end
```
- Onesided shell-like shortcuts:
- Shorter inline condition:
```julia
a<0 && (a = 0)
isfinite(a) || throw_infinite_a_error()
myfunction( index<=10 ? array[index] : default_value )
```
- Shorter inline condition:
- 💡 Useful shell-like shortcuts:
```julia
myfunction( index<=10 ? array[index] : default_value )
a < 0 && (a = 0)
a > 10 && (a = 10)
isfinite(a) || @error "a is infinite, program will crash!"
```
......@@ -207,7 +181,7 @@ Example:
# Structured cycles!
# 💡 Structured cycles!
Using functional-style loops is *much less error-prone* to indexing
errors.
......@@ -246,35 +220,77 @@ julia> join(sort([c for word in ["the result is 123", "what's happening?", "stuf
# Control flow: subroutines (functions and methods)
# Control flow: subroutines (functions)
- Multi-line function definition
- Multi-line function definition
```julia
function f(a,b)
function combine(a,b)
return a + b
end
```
- "Mathematical" definition
- "Mathematical" neater definition
```julia
combine(a,b) = a + b
```
- 💡 Definition with types specified (prevents errors, allows optimizations!)
```julia
f(a,b) = a + b
function combine(a::Int, b::Int)::Int
return a + b
end
```
- Definition with types specified (creates a *method* of a function)
# 💡💡 Control flow: subroutine overloading (methods)
- A method for combining integers
```julia
f(a::Int, b::Int)::Int = a + b
combine(a::Int, b::Int)::Int = a + b
```
- Overloading (adds another *method* to the function)
- A method of the "same function" for combining strings
```julia
f(a::Complex, b::Complex)::Complex = complex(a.re+b.re, a.im+b.im)
combine(a::String, b::String)::String = "$a and $b"
```
(Upon calling the function, Julia picks the *most specific* method.)
# 💡💡💡 Supertype hierarchy
Types possess a single supertype, which allows you to easily group
multiple types under e.g. `Real`, `Function`, `Type`, `Any`, ...
This creates *groups of types* that are useful for restricting your functions to work on the most reasonable subsets of inputs.
<pre style="font-size: 80%; line-height:120%;"><code class="language-julia hljs">
julia> Int
Int64
julia> Int.super
Signed
julia> Int.super.super
Integer
julia> Int.super.super.super
Real
julia> Int.super.super.super.super
Number
julia> Int.super.super.super.super.super
Any
</code></pre>
(Upon calling the function, Julia picks the *most specific* available method.)
......@@ -290,12 +306,12 @@ end
f(123, extra=321)
```
- Managing arguments en masse
- 💡 Managing arguments en masse
```julia
euclidean(x; kwargs...) = sqrt.(sum(x.^2; kwargs...))
max(args...) = maximum(args)
max_squared(args...) = maximum(args .^ 2)
```
......@@ -318,7 +334,7 @@ x = [1,2,3,4]
x' .* x
```
Internally handled by `broadcast()`.
💡 The "magic dot" is a shortcut for calling `broadcast(...)`.
......@@ -335,7 +351,7 @@ person["age"]
indexof(v::Vector) = Dict(v .=> eachindex(v))
```
- Sets are value-less dictionaries (i.e., the elements are unique keys)
- 💡 Sets are key-only containers (keys are _unique_)
```julia
julia> x=Set([1,2,3,2,1]);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment