Introduction Julia features Concluding remarks
The Julia Programming Language: A fresh approach to technical computing
Tim Schoof
1/20 Introduction Julia features Concluding remarks
Sharelatex1
A I Online LTEX editor
A I Complete modern LTEX environment =⇒ no installation needed
I Collaborative real-time editing =⇒ no version conflicts
I Eternal history =⇒ Go back to any point in time
I Bibliography search, comments, chat, github integration, and more
1 sharelatex.com 2/20 Introduction Julia features Concluding remarks
Zotero2
I Organize your bibliography
I Share downloaded papers with the group
I Download pdf and meta-data with a single click
I Full text search in meta-data and pdfs
2 https://www.zotero.org/ 3/20 Introduction Julia features Concluding remarks
History
I Work started 2009 at UC Santa Barbara and MIT (by Stefan Karpinski, Viral Shah, Jeff Bezanson, Alan Edelman)
I First public release 2012
I Julia Computing founded in 2015 (by inventors + Deepak Vinchhi and Keno Fischer)
I 2017 Julia Computing raises $4.6M in seed funding
4/20 Introduction Julia features Concluding remarks
Example 1: Calculate π with Monte Carlo
I Choose M random points within a square (uniformly distributed)
I Count points within enclosed circle, e.g., N
I It follows
N A π(d/2)2 ≈ = M A d2
N =⇒ π ≈ 4 M
I In picture π ≈ 3.15
5/20 Introduction Julia features Concluding remarks
Example 1: Calculate π in C++
1 #include
7 using namespace std;
9 double calc_pi(int M) { int sum = 0; 11 double x; double y; 13 for (int i = 0; i < M; ++i) { 15 x = distUReal(rng); y = distUReal(rng); 17 sum += x*x + y*y < 1; } 19 return 4.0 * sum / M; } 21 int main() 23 { int M = pow(10,9); 25 cout << calc_pi(M) << endl; }
6/20 Introduction Julia features Concluding remarks
Example 1: Calculate π in C++
#include
4 std::mt19937_64 rng; std::uniform_real_distribution
I characterdouble count:x; 432 12 double y; I run time:for 19(int s i = 0; i < M; ++i) 14 { x = distUReal(rng); 16 y = distUReal(rng); sum += x*x + y*y < 1; 18 } return 4.0 * sum / M; 20 }
22 int main() { 24 int M = pow(10,9); cout << calc_pi(M) << endl; 26 }
6/20 Introduction Julia features Concluding remarks
Example 1: Calculate π in Python
from random import random 2 def calc_pi(M): 4 return 4*sum(random()**2 + random()**2 < 1 for i in range(M)) / M
6 print(calc_pi(10**9))
Much shorter due to high level code:
I no type declarations necessary
I predefined functions: sum,…
I range based for loops: for elem in
I generator expressions: (f(elem) for elem in
7/20 Introduction Julia features Concluding remarks
Example 1: Calculate π in Python
from random import random 2 def calc_pi(M): 4 return 4*sum(random()**2 + random()**2 < 1 for i in range(M)) / M
6 print(calc_pi(10**9)) I character count: 135
I run time: 280 s Much shorter due to high level code:
I no type declarations necessary
I predefined functions: sum,…
I range based for loops: for elem in
I generator expressions: (f(elem) for elem in
7/20 Introduction Julia features Concluding remarks
Example 1: Calculate π in Julia
calc_pi(M) = 4*sum(rand()^2 + rand()^2 < 1 for i=1:M) / M 2 println(calc_pi(10^9))
Even shorter syntax:
I many important functions imported by default
I inline function definitions: f(x) = 2x
I ranges: start:stop and start:step:stop
8/20 Introduction Julia features Concluding remarks
Example 1: Calculate π in Julia
calc_pi(M) = 4*sum(rand()^2 + rand()^2 < 1 for i=1:M) / M 2 println(calc_pi(10^9))
I character count: 83
EvenI run shorter time: 7 syntax: s
I many important functions imported by default
I inline function definitions: f(x) = 2x
I ranges: start:stop and start:step:stop
8/20 Introduction Julia features Concluding remarks
Example 2: Micro benchmarks
9/20 Introduction Julia features Concluding remarks
Example 2: Micro benchmarks
10/20 Introduction Julia features Concluding remarks
Example 3: Celeste project
I Locate and characterize light sources in the universe
I Sloan Digital Sky Survey
I 178 TB image data I 188 million stars and galaxies
I 1.54 PFLOPS peak performance
I 9300 nodes I 1.3 million threads on 650,000 KNL cores I <15 min runtime
I Julia first language since C/C++/Fortran reaching >1PFLOPS
11/20 I only inferable Julia code is fast I type-unstable code has Python like performance (or even slower due to missing optimizations) I see also performance tips in manual! (https://docs.julialang.org/en/latest/manual/performance-tips/)
I Aggrassive specialization on argument types
I Language design focused on speed
I avoids hard to optimize language features e.g., dictionary semantics for objects and scopes I machine integers (overflow!) I driven by LLVM’s possibilities from the start
I “Type-stable” standard library
Introduction Julia features Concluding remarks
How is that possible?
I Just-In-Time (JIT) compilation to native machine code
12/20 4 julia> @time f(1) # first call with an Int 0.001466 seconds (244 allocations: 17.041 KiB) 6 2 julia> @time f(1) # second call with an Int 8 0.000003 seconds (4 allocations: 160 bytes) 2 10 julia> @time f(2) # Only the type matters, not the value 12 0.000003 seconds (4 allocations: 160 bytes) 4 14 julia> @time f(1.0) # First call with a Float64 16 0.004278 seconds (215 allocations: 13.104 KiB) 2.0 18 julia> @time f(1.0) 20 0.000003 seconds (5 allocations: 176 bytes) 2.0 22 julia> @time f(2.0) 24 0.000003 seconds (5 allocations: 176 bytes) 4.0
Introduction Julia features Concluding remarks
Just-in-time (JIT) Compilation
A new function is compiled on first use for each combination of argument types3:
julia> f(x) = 2x 2 f (generic function with 1 method)
3 except for functions and types by default 13/20 11 julia> @time f(2) # Only the type matters, not the value 0.000003 seconds (4 allocations: 160 bytes) 13 4
15 julia> @time f(1.0) # First call with a Float64 0.004278 seconds (215 allocations: 13.104 KiB) 17 2.0
19 julia> @time f(1.0) 0.000003 seconds (5 allocations: 176 bytes) 21 2.0
23 julia> @time f(2.0) 0.000003 seconds (5 allocations: 176 bytes) 25 4.0
Introduction Julia features Concluding remarks
Just-in-time (JIT) Compilation
A new function is compiled on first use for each combination of argument types3:
1 julia> f(x) = 2x f (generic function with 1 method) 3 julia> @time f(1) # first call with an Int 5 0.001466 seconds (244 allocations: 17.041 KiB) 2 7 julia> @time f(1) # second call with an Int 0.000003 seconds (4 allocations: 160 bytes) 9 2
3 except for functions and types by default 13/20 15 julia> @time f(1.0) # First call with a Float64 0.004278 seconds (215 allocations: 13.104 KiB) 17 2.0
19 julia> @time f(1.0) 0.000003 seconds (5 allocations: 176 bytes) 21 2.0
23 julia> @time f(2.0) 0.000003 seconds (5 allocations: 176 bytes) 25 4.0
Introduction Julia features Concluding remarks
Just-in-time (JIT) Compilation
A new function is compiled on first use for each combination of argument types3:
1 julia> f(x) = 2x f (generic function with 1 method) 3 julia> @time f(1) # first call with an Int 5 0.001466 seconds (244 allocations: 17.041 KiB) 2 7 julia> @time f(1) # second call with an Int 0.000003 seconds (4 allocations: 160 bytes) 9 2
11 julia> @time f(2) # Only the type matters, not the value 0.000003 seconds (4 allocations: 160 bytes) 13 4
3 except for functions and types by default 13/20 Introduction Julia features Concluding remarks
Just-in-time (JIT) Compilation
A new function is compiled on first use for each combination of argument types3:
1 julia> f(x) = 2x f (generic function with 1 method) 3 julia> @time f(1) # first call with an Int 5 0.001466 seconds (244 allocations: 17.041 KiB) 2 7 julia> @time f(1) # second call with an Int 0.000003 seconds (4 allocations: 160 bytes) 9 2
11 julia> @time f(2) # Only the type matters, not the value 0.000003 seconds (4 allocations: 160 bytes) 13 4
15 julia> @time f(1.0) # First call with a Float64 0.004278 seconds (215 allocations: 13.104 KiB) 17 2.0
19 julia> @time f(1.0) 0.000003 seconds (5 allocations: 176 bytes) 21 2.0
23 julia> @time f(2.0) 0.000003 seconds (5 allocations: 176 bytes) 25 4.0
3 except for functions and types by default 13/20 Introduction Julia features Concluding remarks
Machine code
Julia compiles to native machine code very similar to C++
1 julia> @code_native f(1) .text 3 Filename: REPL[1] pushq %rbp 5 movq %rsp, %rbp Source line: 1 7 leaq (%rdi,%rdi), %rax popq %rbp 9 retq nopw (%rax,%rax) 11 julia> @code_native f(1.0) 13 .text Filename: REPL[1] 15 pushq %rbp movq %rsp, %rbp 17 Source line: 1 vaddsd %xmm0, %xmm0, %xmm0 19 popq %rbp retq 21 nopw (%rax,%rax)
14/20 I only inferable Julia code is fast I type-unstable code has Python like performance (or even slower due to missing optimizations) I see also performance tips in manual! (https://docs.julialang.org/en/latest/manual/performance-tips/)
I Language design focused on speed
I avoids hard to optimize language features e.g., dictionary semantics for objects and scopes I machine integers (overflow!) I driven by LLVM’s possibilities from the start
I “Type-stable” standard library
Introduction Julia features Concluding remarks
How is that possible?
I Just-In-Time (JIT) compilation to native machine code
I Aggrassive specialization on argument types
15/20 I only inferable Julia code is fast I type-unstable code has Python like performance (or even slower due to missing optimizations) I see also performance tips in manual! (https://docs.julialang.org/en/latest/manual/performance-tips/)
I “Type-stable” standard library
Introduction Julia features Concluding remarks
How is that possible?
I Just-In-Time (JIT) compilation to native machine code
I Aggrassive specialization on argument types
I Language design focused on speed
I avoids hard to optimize language features e.g., dictionary semantics for objects and scopes I machine integers (overflow!) I driven by LLVM’s possibilities from the start
15/20 I only inferable Julia code is fast I type-unstable code has Python like performance (or even slower due to missing optimizations) I see also performance tips in manual! (https://docs.julialang.org/en/latest/manual/performance-tips/)
Introduction Julia features Concluding remarks
How is that possible?
I Just-In-Time (JIT) compilation to native machine code
I Aggrassive specialization on argument types
I Language design focused on speed
I avoids hard to optimize language features e.g., dictionary semantics for objects and scopes I machine integers (overflow!) I driven by LLVM’s possibilities from the start
I “Type-stable” standard library
15/20 I Fixed by: f(x) = x > 0 ? x : zero(x)
Introduction Julia features Concluding remarks
Type stability for functions
I A function’s return type depends solely on its input types (not the values) I Example: f(x) = x > 0 ? x : 0
16/20 I Fixed by: f(x) = x > 0 ? x : zero(x)
Introduction Julia features Concluding remarks
Type stability for functions
I A function’s return type depends solely on its input types (not the values) I Example: f(x) = x > 0 ? x : 0
julia> @code_warntype f(1.0) 2 Variables: #self#::#f 4 x::Float64 fx::Float64 6 Body: 8 begin $(Expr(:inbounds, false)) 10 # meta: location operators.jl > 216 # meta: location float.jl < 482 12 fx::Float64 = (Base.sitofp)(Float64, 0)::Float64 # meta: pop location 14 # meta: pop location $(Expr(:inbounds, :pop)) 16 unless (Base.or_int)((Base.lt_float)(fx::Float64, x::Float64)::Bool, (Base.and_int)((Base.eq_float)(fx::Float64, x::Float64)::Bool, (Base.or_int)((Base.eq_float)(fx::Float64, 9.223372036854776e18)::Bool, (Base.slt_int)(0, (Base.fptosi)(Int64, fx::Float64)::Int64)::Bool)::Bool)::Bool)::Bool goto 10 return x::Float64 18 10: return 0 20 end::Union{Float64, Int64}
22 julia> Test.@inferred f(1.0) ERROR: return type Float64 does not match inferred return type 24 Union{Float64, Int64}
16/20 Introduction Julia features Concluding remarks
Type stability for functions
I A function’s return type depends solely on its input types (not the values) I Example: f(x) = x > 0 ? x : 0 I Fixed by: f(x) = x > 0 ? x : zero(x)
julia> @code_warntype f(1.0) 2 Variables: #self#::#f 4 x::Float64 fx::Float64 6 Body: 8 begin $(Expr(:inbounds, false)) 10 # meta: location operators.jl > 216 # meta: location float.jl < 482 12 fx::Float64 = (Base.sitofp)(Float64, 0)::Float64 # meta: pop location 14 # meta: pop location $(Expr(:inbounds, :pop)) 16 unless (Base.or_int)((Base.lt_float)(fx::Float64, x::Float64)::Bool, (Base.and_int)((Base.eq_float)(fx::Float64, x::Float64)::Bool, (Base.or_int)((Base.eq_float)(fx::Float64, 9.223372036854776e18)::Bool, (Base.slt_int)(0, (Base.fptosi)(Int64, fx::Float64)::Int64)::Bool)::Bool)::Bool)::Bool goto 10 return x::Float64 18 10: return (Base.sitofp)(Float64, 0)::Float64 20 end::Float64
16/20 I Fixed by: s = float(one(x))
julia> @code_warntype myexp(1.0f0, 10) 2 Variables: #self#
Introduction Julia features Concluding remarks
Type stability for variables
I A variable only holds values of the same type I Example:
julia> function myexp(x, n=10) 2 s = 1 for k = 1:n 4 s += x^k/factorial(k) end 6 return s end
17/20 I Fixed by: s = float(one(x))
julia> @code_warntype myexp(1.0f0, 10) 2 Variables: #self#
Introduction Julia features Concluding remarks
Type stability for variables
I A variable only holds values of the same type I Example:
julia> function myexp(x, n=10) 2 s = 1 for k = 1:n 4 s += x^k/factorial(k) end 6 return s end
1 julia> @code_warntype myexp(1, 10) Variables: 3 #self#
17/20 Introduction Julia features Concluding remarks
Type stability for variables
I A variable only holds values of the same type I Example:
julia> function myexp(x, n=10) 2 s = 1 for k = 1:n 4 s += x^k/factorial(k) end 6 return s end
I Fixed by: s = float(one(x))
julia> @code_warntype myexp(1.0f0, 10) 2 Variables: #self#
17/20 Introduction Julia features Concluding remarks
How is that possible?
I Just-In-Time (JIT) compilation to native machine code
I Aggrassive specialization on argument types
I Language design focused on speed
I avoids hard to optimize language features e.g., dictionary semantics for objects and scopes I machine integers (overflow!) I driven by LLVM’s possibilities from the start
I “Type-stable” standard library
I only inferable Julia code is fast I type-unstable code has Python like performance (or even slower due to missing optimizations) I see also performance tips in manual! (https://docs.julialang.org/en/latest/manual/performance-tips/)
18/20 Introduction Julia features Concluding remarks
Julia Features
I Dot broadcasting
I Meta programming
I Calling other languages
I GPU programming
19/20 I Compare with single dispatch: o.f(x)
I special syntax for first “argument” o I runtime type of o completely determines which function is called I fields and methods are defined within classes I classes often misused as namespaces
I Multiple dispatch: f(o, x)
I uniform syntax for all function calls I dispatch is determined by the types of all arguments I all arguments are equal I Only fields are defined in structs (abstract types cannot have fields) I methods can be defined everywhere I leads to very modular designs and higher code reuse I use modules to group methods
Introduction Julia features Concluding remarks
Multiple Dispatch
I Julias central programming paradigm
I Post-OOP
I Characteristic look and feel of the language
20/20 I Multiple dispatch: f(o, x)
I uniform syntax for all function calls I dispatch is determined by the types of all arguments I all arguments are equal I Only fields are defined in structs (abstract types cannot have fields) I methods can be defined everywhere I leads to very modular designs and higher code reuse I use modules to group methods
Introduction Julia features Concluding remarks
Multiple Dispatch
I Julias central programming paradigm
I Post-OOP
I Characteristic look and feel of the language
I Compare with single dispatch: o.f(x)
I special syntax for first “argument” o I runtime type of o completely determines which function is called I fields and methods are defined within classes I classes often misused as namespaces
20/20 Introduction Julia features Concluding remarks
Multiple Dispatch
I Julias central programming paradigm
I Post-OOP
I Characteristic look and feel of the language
I Compare with single dispatch: o.f(x)
I special syntax for first “argument” o I runtime type of o completely determines which function is called I fields and methods are defined within classes I classes often misused as namespaces
I Multiple dispatch: f(o, x)
I uniform syntax for all function calls I dispatch is determined by the types of all arguments I all arguments are equal I Only fields are defined in structs (abstract types cannot have fields) I methods can be defined everywhere I leads to very modular designs and higher code reuse I use modules to group methods
20/20 Introduction Julia features Concluding remarks
Multiple Dispatch example
I Multiple dispatch like C++ function overloading with runtime types
abstract type A end 2 foo(x::A, y::A) = 1
4 struct C1 <: A end foo(x::C1, y::A) = 2 6 foo(x::C1, y::C1) = 3
8 struct C2 <: A end
function static() 1 function dynamic() 2 c1 = C1() v = [C1(), C2()] c2 = C2() 3 for e1 in v 4 foo(c1, c1) for e2 in v foo(c1, c2) 5 println(foo(e1,e2)) 6 foo(c2, c1) end foo(c2, c2) 7 end 8 nothing end end static dynamic
Julia C++ Julia C++ C++ code foo(c1, c1) 3 3 3 2 foo(c1, c2) 2 2 2 2 foo(c2, c1) 1 1 1 1 foo(c2, c2) 1 1 1 1 21/20 Introduction Julia features Concluding remarks
Generic programming
I Julia functions are generic by default
function mynorm(v) v u N 2 s = abs(v[1])^2 uX kvk = t |v |2 for i in 2:length(v) i i=1 4 s += abs(v[i])^2 end 6 sqrt(s) end
22/20 Introduction Julia features Concluding remarks
Generic programming
I Julia functions are generic by default
function mynorm(v) v u N 2 s = abs(v[1])^2 uX kvk = t |v |2 for i in 2:length(v) i i=1 4 s += abs(v[i])^2 end 6 sqrt(s) end
1 julia> mynorm([1.0,2.0,3.0]) 3.7416573867739413
22/20 Introduction Julia features Concluding remarks
Generic programming
I Julia functions are generic by default
function mynorm(v) v u N 2 s = abs(v[1])^2 uX kvk = t |v |2 for i in 2:length(v) i i=1 4 s += abs(v[i])^2 end 6 sqrt(s) end
julia> mynorm([1.0,2.0,3.0]) 2 3.7416573867739413
4 julia> mynorm([1.0f0,2.0f0,3.0f0]) 3.7416575f0 6 julia> mynorm([big(1),big(2),big(3)]) 8 3.741657386773941385583748732316549301756019807778726946303745467320035156306928
10 julia> mynorm([1.0 + 1.0im, 2.0 + 2.0im, 3.0 + 3.0im]) 5.291502622129181
22/20 Introduction Julia features Concluding remarks
Generic programming
I Julia functions are generic by default
function mynorm(v) v u N 2 s = abs(v[1])^2 uX kvk = t |v |2 for i in 2:length(v) i i=1 4 s += abs(v[i])^2 end 6 sqrt(s) end
1 julia> using StaticArrays, Unitful.DefaultSymbols
3 julia> mynorm(SVector(1m, 2dm, 3cm)) 1.0202450685987166 m
22/20 Introduction Julia features Concluding remarks
Generic programming
I Julia functions are generic by default
function mynorm(v) v u N 2 s = abs(v[1])^2 uX kvk = t |v |2 for i in 2:length(v) i i=1 4 s += abs(v[i])^2 end 6 sqrt(s) end
julia> using SymPy 2 julia> @syms x positive=true y real=true z 4 (x, y, z)
6 julia> mynorm([sqrt(x), y, z]) ______8 / 2 2 \/ x + y + |z|
22/20 Introduction Julia features Concluding remarks
Generic programming
I Julia functions are generic by default more generic implementation
function mynorm(v) v u N 2 s = abs(v[1])^2 uX kvk = t |v |2 for i in 2:length(v) i i=1 4 s += abs(v[i])^2 end 6 sqrt(s) end
julia> using SymPy 2 julia> @syms x positive=true y real=true z 4 (x, y, z)
6 julia> mynorm([sqrt(x), y, z]) ______8 / 2 2 \/ x + y + |z|
22/20 Introduction Julia features Concluding remarks
Dot broadcasting
I Element-wise operations require a dot, e.g., v .* w v .+ 1 (A*B is matrix multiplication, v + 1 will be an error)
I Every scalar function f(x) can be applied element-wise with f.(v) → read as dotted call operator .(
I Examples:
v.^2 2 exp.(M) f(x) = x > 0 ? x : zero(x) 4 f.(v) strip.(split("a, b, c", ",")) 6 # or: split("a, b, c", ",") .|> strip
I Warning: M^2 / exp(M) might be matrix potentiation/exponentiation in future version
23/20 Introduction Julia features Concluding remarks
Dot fusion
I Multiple vectorized operations are fused into a single loop
I Loop fusion is a syntactic guarantee (might change in the future)
I Example
v = rand(10^6) 2 w = similar(v) f(x) = 3x^2 + 5x + 2 4 w .= f.(2 .* v.^2 .+ 6 .* v.^3 .- sqrt.(v))
I The last statement is allocation free!
I It can also be written as
@. w = f(2v^2 + 6v^3 - sqrt(v))
24/20 Introduction Julia features Concluding remarks
Meta programming
I Macros take an expression as input and replace it with a new expression
I Macro execution happens at compile time
I The new expression is then evaluated as normal
I Simple example
1 julia> @macroexpand @show f(x) quote 3 (Base.println)("f(x) = ", (Base.repr)(begin # show.jl, line 243: #1395#value = f(x) 5 end)) #1395#value 7 end
9 julia> @show f(x) f(x) = 10 11 10
I Useful to create Domain Specific Languages
1 @tensor D[a,b,c] = A[a,e,f,c,f,g]*B[g,b,e] + α*C[c,a,b]
25/20 Introduction Julia features Concluding remarks
Meta programming — generated functions
4 I The following function adds arrays of arbitrary dimensions
1 using Base.Cartesian
3 @generated function add!(out, a, b) N = ndims(out) 5 quote @nloops $N i out begin 7 @nref($N, out, i) = @nref($N, a, i) + @nref($N, b, i) end 9 end end
I Different version is compiled for each combination of input types I Seven dimensional input produces code like
for i_7 = indices(out, 7) 2 for i_6 = indices(out, 6) for i_5 = indices(out, 5) 4 for i_4 = indices(out, 4) for i_3 = indices(out, 3) 6 for i_2 = indices(out, 2) for i_1 = indices(out, 1) 8 out[i_1, i_2, i_3, i_4, i_5, i_6, i_7] = a[i_1, i_2, i_3, i_4, i_5, i_6, i_7] + b[i_1, i_2, i_3, i_4, i_5, i_6, i_7] 10 # Some output omitted
4 https://mikeinnes.github.io/2017/08/24/cudanative.html 26/20 Introduction Julia features Concluding remarks
Calling other languages
I C and Fortran can be called without glue code
I Example
I C function
int main(int argc, char **argv);
I Callable from Julia as
1 argv = [ "a.out", "arg1", "arg2" ] ccall(:main, Int32, (Int32, Ptr{Ptr{UInt8}}), length(argv), argv)
I Interfaces for Python, Matlab, R, …
27/20 Introduction Julia features Concluding remarks
Calling other languages
I C and Fortran can be called without glue code
I Example
I C function
int main(int argc, char **argv);
I Callable from Julia as
1 argv = [ "a.out", "arg1", "arg2" ] ccall(:main, Int32, (Int32, Ptr{Ptr{UInt8}}), length(argv), argv)
I Interfaces for Python, Matlab, R, …
27/20 Introduction Julia features Concluding remarks
GPU programming
I Currently requires self compiled version of Julia
I Custom kernels with CUDAnative
using CuArrays, CUDAnative 2 xs, ys, zs = CuArray(rand(1024)), CuArray(rand(1024)), CuArray(zeros(1024)) 4 function kernel_vadd(out, a, b) 6 i = (blockIdx().x-1) * blockDim().x + threadIdx().x out[i] = a[i] + b[i] 8 return end 10 @cuda (1, length(xs)) kernel_vadd(zs, xs, ys)
I High level syntax with GPUArrays and dot broadcasting
1 zs .= xs.^2 .+ ys .* 2 sum(zs)
28/20 Introduction Julia features Concluding remarks
GPU programming — benchmark
I Speed comparable with CUDA C++ 5 I Partial port the Rodinia benchmark suite :
5 https://devblogs.nvidia.com/parallelforall/gpu-computing-julia-programming-language/ 29/20 Introduction Julia features Concluding remarks
When Julia shouldn’t be used
When one needs
I Language stability
I Stable release 1.0 “soon” (∼ until summer) I Breaking release 2.0 planned in a few years I Packages will need some time after 1.0 to stabilize I Deprecation warnings and FemtoCleaner ease transitions
I Fast startup times
I Adapt workflow: use REPL/Juno/VSCode and Revise.jl to keep Julia running I Might be improved with interpreter and delayed compilation in the future
I Real-time computing
I Garbage collector optimized for throughput instead of latency
30/20 Introduction Julia features Concluding remarks
The future
I Julia is rapidly growing
I 1.2 million downloads per month I Already more contributers (636 since 2012) than python (409 since 1990), numpy (573 since 2002), or scipy (550 since 2001)
I Julia blurs the distinction between users and developers
I Most code of the standard library and packages is written in Julia I @edit func(args) opens source code in editor I Pkg.checkout, Pkg.test, and PkgDev.submit help to create pull request to existing package I PkgDev.generate and PkgDev.register help to create new packages
I Compiler optimizations “barely scratched the surface”
I More optimizations are planned for 1.x versions
I Better tooling
I Improved package manager I Debugger
31/20 Introduction Julia features Concluding remarks
Summary
I Julia combines C-like speed with Python-like convenience
I Powerful features
I Multiple dispatch I Generic programming I Dot broadcasting I Meta programming I Calling other languages I GPU programming
I Try it yourself
I Completely open source (MIT license) I Single binary, no installation required
32/20 Introduction Julia features Concluding remarks
Thank you for your attention!
33/20 More generic implementation of norm Return
I The simple mynorm function …
I …works only for indexable collections I …assumes 1 is the first index I …fails on empty collections
I Use the iterator protocol to allow general iterable arguments
julia> function mynorm(it) 2 state = start(it) done(it, state) && return float(real(zero(eltype(it)))) 4 elem, state = next(it, state) sum = abs2(elem) 6 while !done(it, state) elem, state = next(it, state) 8 sum += abs2(elem) end 10 return sqrt(sum) end 12 julia> mynorm(i^2 for i=1:3) 14 9.899494936611665
34/20 Dispatch in C++ Return
#include
4 // abstract base class 1 int main() { class A{ 6 public: 3 std::cout << "Static:" << std::endl; virtual int foo(A* a) { C1 c1 = C1(); 8 return 1; 5 C2 c2 = C2(); } std::cout << c1.foo(&c1) << std::endl; 10 }; 7 std::cout << c1.foo(&c2) << std::endl; std::cout << c2.foo(&c1) << std::endl; 12 // a concrete class with special behavior 9 std::cout << c2.foo(&c2) << std::endl; class C1 : public A{ 14 public: 11 std::cout << "Dynamic::" << std::endl; virtual int foo(A* a) { std::vector v {new C1(), new C2()}; 16 return 2; 13 for (auto e1: v) { } for (auto e2: v) { 18 virtual int foo(C1* a) { 15 std::cout << e1->foo(e2) << std::endl; return 3; } 20 } 17 } }; } 22 // a concrete class with default behavior 24 class C2 : public A{ };
35/20