Examples
Mandelbrot
from
test_mandelbrot
of numba/tests/doc_examples/test_examples.py
1from timeit import default_timer as timer
2try:
3 from matplotlib.pylab import imshow, show
4 have_mpl = True
5except ImportError:
6 have_mpl = False
7import numpy as np
8from numba import jit
9
10@jit(nopython=True)
11def mandel(x, y, max_iters):
12 """
13 Given the real and imaginary parts of a complex number,
14 determine if it is a candidate for membership in the Mandelbrot
15 set given a fixed number of iterations.
16 """
17 i = 0
18 c = complex(x,y)
19 z = 0.0j
20 for i in range(max_iters):
21 z = z * z + c
22 if (z.real * z.real + z.imag * z.imag) >= 4:
23 return i
24
25 return 255
26
27@jit(nopython=True)
28def create_fractal(min_x, max_x, min_y, max_y, image, iters):
29 height = image.shape[0]
30 width = image.shape[1]
31
32 pixel_size_x = (max_x - min_x) / width
33 pixel_size_y = (max_y - min_y) / height
34 for x in range(width):
35 real = min_x + x * pixel_size_x
36 for y in range(height):
37 imag = min_y + y * pixel_size_y
38 color = mandel(real, imag, iters)
39 image[y, x] = color
40
41 return image
42
43image = np.zeros((500 * 2, 750 * 2), dtype=np.uint8)
44s = timer()
45create_fractal(-2.0, 1.0, -1.0, 1.0, image, 20)
46e = timer()
47print(e - s)
48if have_mpl:
49 imshow(image)
50 show()
Moving average
from
test_moving_average
of numba/tests/doc_examples/test_examples.py
1import numpy as np
2
3from numba import guvectorize
4
5@guvectorize(['void(float64[:], intp[:], float64[:])'],
6 '(n),()->(n)')
7def move_mean(a, window_arr, out):
8 window_width = window_arr[0]
9 asum = 0.0
10 count = 0
11 for i in range(window_width):
12 asum += a[i]
13 count += 1
14 out[i] = asum / count
15 for i in range(window_width, len(a)):
16 asum += a[i] - a[i - window_width]
17 out[i] = asum / count
18
19arr = np.arange(20, dtype=np.float64).reshape(2, 10)
20print(arr)
21print(move_mean(arr, 3))
Multi-threading
The code below showcases the potential performance improvement when using the nogil feature. For example, on a 4-core machine, the following results were printed:
numpy (1 thread) 145 ms
numba (1 thread) 128 ms
numba (4 threads) 35 ms
Note
If preferred it’s possible to use the standard concurrent.futures module rather than spawn threads and dispatch tasks by hand.
from
test_no_gil
of numba/tests/doc_examples/test_examples.py
1import math
2import threading
3from timeit import repeat
4
5import numpy as np
6from numba import jit
7
8nthreads = 4
9size = 10**6
10
11def func_np(a, b):
12 """
13 Control function using Numpy.
14 """
15 return np.exp(2.1 * a + 3.2 * b)
16
17@jit('void(double[:], double[:], double[:])', nopython=True,
18 nogil=True)
19def inner_func_nb(result, a, b):
20 """
21 Function under test.
22 """
23 for i in range(len(result)):
24 result[i] = math.exp(2.1 * a[i] + 3.2 * b[i])
25
26def timefunc(correct, s, func, *args, **kwargs):
27 """
28 Benchmark *func* and print out its runtime.
29 """
30 print(s.ljust(20), end=" ")
31 # Make sure the function is compiled before the benchmark is
32 # started
33 res = func(*args, **kwargs)
34 if correct is not None:
35 assert np.allclose(res, correct), (res, correct)
36 # time it
37 print('{:>5.0f} ms'.format(min(repeat(
38 lambda: func(*args, **kwargs), number=5, repeat=2)) * 1000))
39 return res
40
41def make_singlethread(inner_func):
42 """
43 Run the given function inside a single thread.
44 """
45 def func(*args):
46 length = len(args[0])
47 result = np.empty(length, dtype=np.float64)
48 inner_func(result, *args)
49 return result
50 return func
51
52def make_multithread(inner_func, numthreads):
53 """
54 Run the given function inside *numthreads* threads, splitting
55 its arguments into equal-sized chunks.
56 """
57 def func_mt(*args):
58 length = len(args[0])
59 result = np.empty(length, dtype=np.float64)
60 args = (result,) + args
61 chunklen = (length + numthreads - 1) // numthreads
62 # Create argument tuples for each input chunk
63 chunks = [[arg[i * chunklen:(i + 1) * chunklen] for arg in
64 args] for i in range(numthreads)]
65 # Spawn one thread per chunk
66 threads = [threading.Thread(target=inner_func, args=chunk)
67 for chunk in chunks]
68 for thread in threads:
69 thread.start()
70 for thread in threads:
71 thread.join()
72 return result
73 return func_mt
74
75func_nb = make_singlethread(inner_func_nb)
76func_nb_mt = make_multithread(inner_func_nb, nthreads)
77
78a = np.random.rand(size)
79b = np.random.rand(size)
80
81correct = timefunc(None, "numpy (1 thread)", func_np, a, b)
82timefunc(correct, "numba (1 thread)", func_nb, a, b)
83timefunc(correct, "numba (%d threads)" % nthreads, func_nb_mt, a, b)