Benchmarking, profiling and optimizing (II)ο
Profilingο
Scaleneο
Scalene is a sampling profiler. In addition to timings , it can also give insight into:
CPU time spent in Python (interpreted), native (compiled) and system function calls
Memory usage and copy
GPU utilization
Memory leak detection
Moreover, it adds minimal overhead due to profiling. The downside is the results are less reproducible, because it is a sampling profiler.
Scalene can be used as a CLI tool, or using IPython magic or in
Web interface as an interactive widget. Here are some examples profiling
walk.py with Scalene.
CLI toolο
$ scalene --cli walk.py
IPython magicο
This allows for profiling a specific function. For example to profile just walk, we do as follows:
In [1]: %load_ext scalene
In [2]: %run walk.py
In [3]: %scrun --cli walk(n)
Gives the following output:
SCRUN MAGIC
/home/ashwinmo/Sources/enccs/hpda-python/content/example/walk.py: % of time = 100.00% (1.933s) out of 1.933s.
β· β· β· β· β·
βTime βββββββ βββββββ βββββββ β
Line βPython βnative βsystem βGPU β/home/ashwinmo/Sources/enccs/hpda-python/content/example/walk.py
βΊβββββββΏββββββββΏββββββββΏββββββββΏββββββββΏββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΈ
1 β β β β β"""A 1-D random walk.
2 β β β β β
3 β β β β βSee also:
4 β β β β β- https://lectures.scientific-python.org/intro/numpy/auto_examples/plot_randomwalk.html
5 β β β β β
6 β β β β β"""
7 β β β β βimport numpy as np
8 β β β β β
9 β β β β β
10 β 6% β β β βdef step():
11 β β β β β import random
12 β 7% β 64% β 13% β β return 1.0 if random.random() > 0.5 else -1.0
13 β β β β β
14 β β β β β
15 β β β β βdef walk(n: int, dx: float = 1.0):
16 β β β β β """The for-loop version.
17 β β β β β
18 β β β β β Parameters
19 β β β β β ----------
20 β β β β β n: int
21 β β β β β Number of time steps
22 β β β β β
23 β β β β β dx: float
24 β β β β β Step size. Default step size is unity.
25 β β β β β
26 β β β β β """
27 β β β β β xs = np.zeros(n)
28 β β β β β
29 β β β β β for i in range(n - 1):
30 β β β β β x_new = xs[i] + dx * step()
31 β 7% β β β β xs[i + 1] = x_new
32 β β β β β
33 β β β β β return xs
34 β β β β β
35 β β β β β
36 β β β β βdef walk_vec(n: int, dx: float = 1.0):
37 β β β β β """The vectorized version of :func:`walk` using numpy functions."""
38 β β β β β import random
39 β β β β β steps = np.array(random.sample([1, -1], k=n, counts=[10 * n, 10 * n]))
40 β β β β β
41 β β β β β # steps = np.random.choice([1, -1], size=n)
42 β β β β β
43 β β β β β dx_steps = dx * steps
44 β β β β β
45 β β β β β # set initial condition to zero
46 β β β β β dx_steps[0] = 0
47 β β β β β # use cumulative sum to replicate time evolution of position x
48 β β β β β xs = np.cumsum(dx_steps)
49 β β β β β
50 β β β β β return xs
51 β β β β β
52 β β β β β
53 β β β β βif __name__ == "__main__":
54 β β β β β n = 1_000_000
55 β β β β β _ = walk(n)
56 β β β β β _ = walk_vec(n)
57 β β β β β
β β β β β
βΆβββββββΌββββββββΌββββββββΌββββββββΌββββββββΌββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ΄
β β β β βfunction summary for /home/ashwinmo/Sources/enccs/hpda-python/content/example/walk.py
10 β 14% β 69% β 9% β βstep
15 β 7% β β β βwalk
β΅ β΅ β΅ β΅
If you run the magic command in Jupyter you can use %scrun walk(n) instead and it should an output similar to the Web interface below.
Web interfaceο
Running
$ scalene walk.py
opens up the following web app: