https://github.com/flatironinstitute/sciware/tree/main/19_Profiling
Activities where participants all actively work to foster an environment which encourages participation across experience levels, coding language fluency, technology choices*, and scientific disciplines.
*though sometimes we try to expand your options
(These will always be a work in progress and will be updated, clarified, or expanded as needed.)
time
utility – program timingtimeit
(Python) – testing small Python snippetstime
/usr/bin/time
or /bin/time
time
(a shell built-in)real
, user
, sys
timestime
$ /usr/bin/time -p EXECUTABLE
sciware/19_Profiling/python_example/
So on my laptop:
$ /usr/bin/time -p src/sciware/19_Profiling/python_example/simulation.py
time
showsreal
= wall timeuser
= time executing YOUR codesys
= time in operating system callsreal
likely isn’t user + sys
time
doesn’t showtime
htop
!)iowait
)timeit
timeit
python -m timeit 'print("Hello world!")'
timeit
output100000 loops
)best of 5
)Vector manipuations with built-in arrays and explicit loops:
python -m timeit "
a = range(100)
b = range(99, -1, -1)
c = []
for x, index in enumerate(a):
c.append(x + b[index])
d = []
for x in a:
d.append(6 * x)
print(c, file=sys.stderr)
print(d, file=sys.stderr)
"
The same vector manipulations with numpy arrays:
python -m timeit "
import numpy as np
a = np.arange(100)
b = np.arange(99, -1, -1)
c = a + b
d = 6 * a
print(c, file=sys.stderr)
print(d, file=sys.stderr)
"
...
print(d, file=sys.stderr)
" 2>/dev/null
2>/dev/null
print
statements entirely?
sciware/19_profiling/python_example/simulation.py
python3
with numpy
, snakeviz
, and line-profiler
module load python
source ~rblackwell/envs/sciware_19/bin/activate
sciware/19_profiling/python_example/simulation.py
sciware/19_profiling/julia_example
BenchmarkTools
PProf
FlameGraphs
FileIO
install_prereqs.jl
@time
Pt. 1
function copy_cols(x::Vector{Float64})
n = size(x, 1)
out = zeros(Float64, n, n)
for i = 1:n
out[:, i] = x
end
out
end
function copy_rows(x::Vector{Float64})
n = size(x, 1)
out = zeros(Float64, n, n)
for i = 1:n
out[i, :] = x
end
out
end
@time
Pt. 2function main()
N = Int(1e4)
x = randn(N)
println("Copying vector to columns")
@time copy_cols(x)
println("Copying vector to rows")
@time copy_rows(x)
end
@time
Pt. 3➜ julia 01_timer.jl
Copying vector to columns
0.354818 seconds (2 allocations: 762.939 MiB, 1.12% gc time)
Copying vector to rows
1.033734 seconds (2 allocations: 762.939 MiB, 3.08% gc time)
@profile
Pt. 1
function add_no_prealloc(x::Vector{Float64})
x_new = x .+ 3.0
return x_new
end
function add_prealloc!(x::Vector{Float64})
x .+= 3.0
nothing
end
@profile
Pt. 2function main()
x = zeros(10)
println("\nShowing the profiling info")
@profile (
for i = 1:1e7
add_no_prealloc(x)
add_prealloc!(x)
end
)
Profile.print(format = :tree, maxdepth = 12)
end
@profile
Pt. 3
Showing the profiling info
Overhead ╎ [+additional indent] Count File:Line; Function
=========================================================
╎398 @Base/client.jl:495; _start()
╎ 398 @Base/client.jl:292; exec_options(opts::Base.JLOptions)
╎ 398 @Base/Base.jl:418; include(mod::Module, _path::String)
╎ 398 @Base/loading.jl:1253; _include(mapexpr::Function, mod::Module, _path::String)
╎ 398 @Base/loading.jl:1196; include_string(mapexpr::typeof(identity), mod::Module, code::String, filename::String)
╎ 398 @Base/boot.jl:373; eval
12╎ ╎ 12 ...ojects/sciware/19_Profiling/julia_example/02_profiling.jl:5; add_no_prealloc(x::Vector{Float64})
4╎ ╎ 4 ...ojects/sciware/19_Profiling/julia_example/02_profiling.jl:7; add_no_prealloc(x::Vector{Float64})
1╎ ╎ 1 ...ojects/sciware/19_Profiling/julia_example/02_profiling.jl:10; add_prealloc!(x::Vector{Float64})
╎ ╎ 381 ...ojects/sciware/19_Profiling/julia_example/02_profiling.jl:38; main()
╎ ╎ 381 ...k-src/usr/share/julia/stdlib/v1.7/Profile/src/Profile.jl:28; macro expansion
7╎ ╎ 332 ...jects/sciware/19_Profiling/julia_example/02_profiling.jl:40; macro expansion
3╎ ╎ 3 @Base/simdloop.jl:0; add_no_prealloc(x::Vector{Float64})
10╎ ╎ 10 ...jects/sciware/19_Profiling/julia_example/02_profiling.jl:5; add_no_prealloc(x::Vector{Float64})
╎ ╎ 311 ...jects/sciware/19_Profiling/julia_example/02_profiling.jl:6; add_no_prealloc(x::Vector{Float64})
1╎ ╎ 1 ...jects/sciware/19_Profiling/julia_example/02_profiling.jl:7; add_no_prealloc(x::Vector{Float64})
2╎ ╎ 49 ...jects/sciware/19_Profiling/julia_example/02_profiling.jl:41; macro expansion
╎ ╎ 41 ...ects/sciware/19_Profiling/julia_example/02_profiling.jl:11; add_prealloc!(x::Vector{Float64})
6╎ ╎ 6 ...ects/sciware/19_Profiling/julia_example/02_profiling.jl:12; add_prealloc!(x::Vector{Float64})
Total snapshots: 800
PProf
Pt. 1
function complicated_func()
# Pick parameters for our function
p = [0.1, -0.5, 0.42, -3, 0.01, -0.2]
n = 2000000
# Setting up our data
x = LinRange(0, 10, n)
y = zeros(length(x))
for i = 1:length(p)
y .+= p[i] * x .^ i
end
# Add some noise
y .+= rand(n) * 0.01
# Setup X for solving
X = zeros(Float64, (length(x), length(p)))
for i = 1:length(p)
X[:, i] = x .^ i
end
# Solve Xβ=y
β = X \ y
error = (β - p) / norm(p)
println("Relative error in coefficients ", error)
end
PProf
Pt. 2@profile
to collect information about our function of interest (complicated_func()
)_03_profile_data.jlprof
function main()
@profile complicated_func()
Profile.print(format = :tree, maxdepth = 9)
# Save the data for later
save("_03_profile_data.jlprof", Profile.retrieve()...)
end
PProf
Pt. 3pprof()
to analyze the profiling datajulia> using PProf, FlameGraphs, FileIO
julia> data = load("_03_profile_data.jlprof")
julia> g = flamegraph(data[1]; lidict=data[2])
julia> pprof(g)
PProf
Pt. 3PProf
interface in a browser (something like: http://localhost:57599)
PProf
Pt. 4-g -pg
-O
)gcc
, g++
, gfortran
, clang
, clang++
gmon.out
GMON_OUT_PREFIX=foo ./myprog
produces foo.PID
gprof myprog gmon.out
#define
):
unordered_map