Theory Lunch 29/03/2021
... a Fast, Dynamic, Reproducible, Composable, General, and Open source programming language.
Developed at MIT ~ 9 years ago
Jeff Bezanson, Alan Edelman, Stefan Karpinski, Viral B. Shah
C
Julia
Python
int sum(int a, int b)
{
return a + b;
}
int main(){
int a = 2;
int b = 3;
int c = sum(a, b);
}
C
def sum(a, b):
return a + b
>>> sum(1, 2)
3
>>> sum("hello", " world")
"hello world"
Python
For speed you want static types.
function product(a, b)
return a * b
end
Came for the speed, stayed for the syntax
Mapping
Argument
types
Function
Python
C
Julia
0
1
n
Dispatch
arguments
Function
+
Methods
a + b
a[i] + b[i]...
a = 1
b = 2
@which a * b
*(x::T, y::T) where T<:Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8} in Base at int.jl:88
a = "hello"
b = " world!"
@which a * b
*(s1::Union{AbstractChar, AbstractString}, ss::Union{AbstractChar, AbstractString}...) in Base at strings/basic.jl:260
How many methods does '*' have?
all_methods = collect(methods(*))
>>> length(all_methods)
336
all_methods[19]
*(A::Union{LinearAlgebra.LowerTriangular, LinearAlgebra.UnitLowerTriangular}, B::LinearAlgebra.Bidiagonal) in LinearAlgebra at /home/arnau/opt/julia-1.6.0-rc3/share/julia/stdlib/v1.6/LinearAlgebra/src/bidiag.jl:658
Two kinds of types: Abstract and Concrete
Variables always instances of concrete type
abstract type CelestialBody end
struct Star <: CelestialBody
M
end
struct Planet <: CelestialBody
M
end
struct Galaxy <: CelestialBody
M_bulge
M_disc
end
mass(body::CelestialBody) = body.M
>>> methods(mass)
# 1 method for generic function mass:
>>> sun = Star(1)
>>> mass(sun)
1
>>> milky_way = Galaxy(1e10, 1e12)
>>> mass(milky_way)
error: type Galaxy has no field M
mass(galaxy::Galaxy) = galaxy.M_bulge + galaxy.M_disc
>>> methods(mass)
# 2 methods for generic function mass:
>>> mass(milky_way)
1.01e12
Julia always calls the most restrictive method
mass(object) = error("This function only
works for Celestial objects")
>>> mass("test")
error: This function only works for Celestial objects
If the type is not specified, then it works for any input (like Python)
Data
Functions
# Python
class BlackHole:
def __init__(self, M):
self.M = M
def compute_schwarzschild_radius(self):
return np.sqrt(2 * G * self.M / C)
How can we expand the class?
class NewBlackHole(BlackHole):
def new_method(self):
...
struct BlackHole
M
end
function compute_schwarzschild_radius(bh::BlackHole)
return sqrt(2 * G * bh.M) / C
end
new_method(bh::BlackHole) = ...
Julia natively supports parallelism (CPU and GPU)
using Distributed
addprocs(3) # I want 3 CPU workers
@everywhere function expensive_function(i)
println("I am process $(myid()) calculating $i")
sleep(2)
end
pmap(expensive_function, 1:10)
You can spawn processes through Slurm!
using ClusterManagers
addprocs_slurm(16, A="durham", p="cosma", t="01:00:00")
Bonus : Revise.jl
Revise.jl automatically recompiles code in interactive sessions.
Similar to %autoreload magic in IPython.
Very easy to call Python, C and Fortran code in Julia
using PyCall
scipy = pyimport("scipy")
# now we can use all scipy functions!
x = range(1, 100, length=50)
y = x .^ 2
interp = scipy.interpolate.interp1d(x, y)
>>> interp([1,2,3,4])
...
Matlab-like dot syntax
>>> f(x) = x^2
>>> vector = [1, 2, 3, 4, 5]
>>> f.(x)
[1, 4, 9, 16, 25]
Equivalent to map(f, vector)
Unicode support
This is not Latex, it is legit Julia code!
Even plots in unicode!
I encourage you to try Julia if:
If your main focus is data analysis with no algorithm development, Python is the best option (for now).
Slides: slides.com/astrobyte/julia