Skip to content

Commit 9d7c7aa

Browse files
committed
adding exercises
1 parent a69788f commit 9d7c7aa

5 files changed

+168
-17
lines changed

01 - Go fast with Numba.ipynb

+46-4
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,9 @@
8080
"cell_type": "markdown",
8181
"metadata": {},
8282
"source": [
83-
"As you can see, the time that run the function with compliation for the 1st time is much slower than runing it without the complilation. However, after compliation, it is way faster. \n",
83+
"As you can see, the time that run the function with compliation for the 1st time is much slower than runing it without the complilation. However, after compliation, it is way faster.\n",
84+
"\n",
85+
"**Question: Why it is slower the 1st time?**\n",
8486
"\n",
8587
"So we always have a trade off. If the function is only used a couple of times, it may as will be better without the compliation."
8688
]
@@ -242,7 +244,45 @@
242244
"source": [
243245
"As you see now, the different between the vetor operation and the elementwise looping operation is almost none. In other words, the `@njit` speed up the operation almost 10 folds.\n",
244246
"\n",
245-
"There are still improvement of the vector operations but it is not as much as the elementwise looping."
247+
"There are still improvement of the vector operations but it is not as much as the elementwise looping.\n",
248+
"\n",
249+
"**Exercise: Can you change the following into elementwise operation?**"
250+
]
251+
},
252+
{
253+
"cell_type": "code",
254+
"execution_count": null,
255+
"metadata": {},
256+
"outputs": [],
257+
"source": [
258+
"def julia_fast(mesh, c=-1, num_iter=10, radius=2):\n",
259+
"\n",
260+
" z = mesh.copy()\n",
261+
" diverge_len = np.zeros(z.shape)\n",
262+
"\n",
263+
" for i in range(num_iter):\n",
264+
" conv_mask = np.abs(z) < radius\n",
265+
" z[conv_mask] = np.square(z[conv_mask]) + c\n",
266+
" diverge_len[conv_mask] += 1\n",
267+
"\n",
268+
" return diverge_len"
269+
]
270+
},
271+
{
272+
"cell_type": "code",
273+
"execution_count": null,
274+
"metadata": {},
275+
"outputs": [],
276+
"source": []
277+
},
278+
{
279+
"cell_type": "code",
280+
"execution_count": null,
281+
"metadata": {},
282+
"outputs": [],
283+
"source": [
284+
"# Un-commend the line below to see how we do it.\n",
285+
"#%load element_op.py"
246286
]
247287
},
248288
{
@@ -314,7 +354,7 @@
314354
"cell_type": "markdown",
315355
"metadata": {},
316356
"source": [
317-
"As you see, the fast math version is takes almost only half the time. (Is it?)"
357+
"As you see, the fast math version is takes almost only half the time."
318358
]
319359
},
320360
{
@@ -359,7 +399,9 @@
359399
"cell_type": "markdown",
360400
"metadata": {},
361401
"source": [
362-
"Depending on how many cores your have on your computer, you will see carious degrees of improvement. On my 3.1 GHz Dual-Core Intel Core i7 early 2015 MacBook Pro, it is slightly faster than the one using njit and almost 7 times faster than without compilation."
402+
"Depending on how many cores your have on your computer, you will see carious degrees of improvement. On my 3.1 GHz Dual-Core Intel Core i7 early 2015 MacBook Pro, it is slightly faster than the one using njit and almost 7 times faster than without compilation. On my new 8 Core M2 2022 Macbook air, it is 10 times faster. \n",
403+
"\n",
404+
"**Question: What about yours?**"
363405
]
364406
},
365407
{

02 - What can go wrong and how to fix it.ipynb

+93-13
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"metadata": {},
66
"source": [
77
"## Python object vs nopython mode\n",
8-
"A lof of times, we will run into compilation problem that we will never exepriecne with Numba. It is because, in pure Python we do not complie any code. Here is an example of how we can run into a compilation error when using nopython mode"
8+
"A lof of times, we will run into compilation problem that we will never exepriecne with Numba. It is because, in pure Python we do not complie any code. Here is an example of how we can run into a compilation error when using nopython mode\n",
9+
"\n",
10+
"First consider the code below:"
911
]
1012
},
1113
{
@@ -14,11 +16,80 @@
1416
"metadata": {},
1517
"outputs": [],
1618
"source": [
17-
"from numba import njit\n",
18-
"\n",
19-
"@njit #remember that njit is the short hand for @jit(nopython=True)\n",
2019
"def adding_numbers(x, y):\n",
21-
" return int(x) + int(y)"
20+
" return x + y"
21+
]
22+
},
23+
{
24+
"cell_type": "markdown",
25+
"metadata": {},
26+
"source": [
27+
"It is a simple function adding two numbers so"
28+
]
29+
},
30+
{
31+
"cell_type": "code",
32+
"execution_count": null,
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"adding_numbers(1,2)"
37+
]
38+
},
39+
{
40+
"cell_type": "markdown",
41+
"metadata": {},
42+
"source": [
43+
"would gives you 3, let's try change the first input into a string."
44+
]
45+
},
46+
{
47+
"cell_type": "code",
48+
"execution_count": null,
49+
"metadata": {},
50+
"outputs": [],
51+
"source": [
52+
"adding_numbers(\"1\",2)"
53+
]
54+
},
55+
{
56+
"cell_type": "markdown",
57+
"metadata": {},
58+
"source": [
59+
"Would have an error as we are trying to add a string to an integer.\n",
60+
"\n",
61+
"**Exercise: change the code in \"adding_numbers\" to \"fix\" the above**"
62+
]
63+
},
64+
{
65+
"cell_type": "code",
66+
"execution_count": null,
67+
"metadata": {},
68+
"outputs": [],
69+
"source": []
70+
},
71+
{
72+
"cell_type": "markdown",
73+
"metadata": {},
74+
"source": [
75+
"**Exercise: use `njit` on the \"fixed\" function**"
76+
]
77+
},
78+
{
79+
"cell_type": "code",
80+
"execution_count": null,
81+
"metadata": {},
82+
"outputs": [],
83+
"source": []
84+
},
85+
{
86+
"cell_type": "code",
87+
"execution_count": null,
88+
"metadata": {},
89+
"outputs": [],
90+
"source": [
91+
"# Un-commend the line below to see how we do it.\n",
92+
"#%load adding_numbers.py"
2293
]
2394
},
2495
{
@@ -59,19 +130,26 @@
59130
"source": [
60131
"We see a compilation error that we would never see when using pure Python. This is an error that came from Numba. From the Traceback we see there is an error message that mension TypingError and it's something to do with the nopython mode pipeline.\n",
61132
"\n",
62-
"So let's try to make Python object avaliable."
133+
"So let's try to make Python object avaliable.\n",
134+
"\n",
135+
"**Exercise: rename \"adding_numbers\" to \"adding_numbers_again\" and use `jit` on it**"
63136
]
64137
},
138+
{
139+
"cell_type": "code",
140+
"execution_count": null,
141+
"metadata": {},
142+
"outputs": [],
143+
"source": []
144+
},
65145
{
66146
"cell_type": "code",
67147
"execution_count": null,
68148
"metadata": {},
69149
"outputs": [],
70150
"source": [
71-
"from numba import jit\n",
72-
"@jit\n",
73-
"def adding_numbers_again(x, y):\n",
74-
" return int(x) + int(y)"
151+
"# Un-commend the line below to see how we do it.\n",
152+
"#%load adding_numbers_again.py"
75153
]
76154
},
77155
{
@@ -94,7 +172,7 @@
94172
"cell_type": "markdown",
95173
"metadata": {},
96174
"source": [
97-
"Now we see that the g function does compiled, we ony get a warning from Numba, which says we are now using object mode. (so it will be slower than expected, see **Extra Task** below)\n",
175+
"Now we see that the function does compiled, we ony get a warning from Numba, which says we are now using object mode. (so it will be slower than expected, see **Extra Task** below)\n",
98176
"\n",
99177
"Now it is your turn to try.\n",
100178
"\n",
@@ -130,7 +208,7 @@
130208
"source": [
131209
"It is quite fustriting as we cannot compile this function, it is due to Numba not able to determine the return type of a function for compilation. Maybe the Python interpreter can help?\n",
132210
"\n",
133-
"**TODO: use the proper decorator for the function below**"
211+
"**Exercise: use the proper decorator for the function below**"
134212
]
135213
},
136214
{
@@ -250,7 +328,9 @@
250328
"cell_type": "markdown",
251329
"metadata": {},
252330
"source": [
253-
"Now, can you figure it out a way to return an empty list using `njit`? We have to somehow state the type of the items in the list without putting any items in the list..."
331+
"Now, can you figure it out a way to return an empty list using `njit`? We have to somehow state the type of the items in the list without putting any items in the list...\n",
332+
"\n",
333+
"**Exercise: try to \"fix\" the above**"
254334
]
255335
},
256336
{

adding_numbers.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from numba import njit
2+
3+
@njit #remember that njit is the short hand for @jit(nopython=True)
4+
def adding_numbers(x, y):
5+
return int(x) + int(y)

adding_numbers_again.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from numba import jit
2+
@jit
3+
def adding_numbers_again(x, y):
4+
return int(x) + int(y)

element_op.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@jit(nopython=True, nogil=True)
2+
def element_op(z, div_len, c, radius):
3+
for x in range(z.shape[0]):
4+
for y in range(z.shape[1]):
5+
if np.abs(z[x][y]) < radius:
6+
z[x][y] = np.square(z[x][y]) + c
7+
div_len[x][y] +=1
8+
return z, div_len
9+
10+
11+
@jit(nopython=True,nogil=True)
12+
def julia_fast(mesh, c=-1, num_iter=10, radius=2):
13+
14+
z = mesh.copy()
15+
diverge_len = np.zeros(z.shape)
16+
17+
for i in range(num_iter):
18+
z, diverge_len = element_op(z, diverge_len, c,radius)
19+
20+
return diverge_len

0 commit comments

Comments
 (0)