You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
FIX: Update Numba Lecture to Address Deprecation of @jit (#296)
* update a section on type inference.
* update lecture to avoid literal box warning
* check the type of the function
* Update lectures/numba.md
Co-authored-by: mmcky <[email protected]>
* reduce redundancy
* further simplifies descriptions
* fix typos
---------
Co-authored-by: mmcky <[email protected]>
In addition to what's in Anaconda, this lecture will need the following libraries:
28
30
29
-
```{code-cell} ipython
30
-
---
31
-
tags: [hide-output]
32
-
---
31
+
```{code-cell} ipython3
32
+
:tags: [hide-output]
33
+
33
34
!pip install quantecon
34
35
```
35
36
@@ -38,7 +39,7 @@ versions are a {doc}`common source of errors <troubleshooting>`.
38
39
39
40
Let's start with some imports:
40
41
41
-
```{code-cell}ipython
42
+
```{code-cell}ipython3
42
43
%matplotlib inline
43
44
import numpy as np
44
45
import quantecon as qe
@@ -98,13 +99,13 @@ $$
98
99
99
100
In what follows we set
100
101
101
-
```{code-cell}python3
102
+
```{code-cell}ipython3
102
103
α = 4.0
103
104
```
104
105
105
106
Here's the plot of a typical trajectory, starting from $x_0 = 0.1$, with $t$ on the x-axis
106
107
107
-
```{code-cell}python3
108
+
```{code-cell}ipython3
108
109
def qm(x0, n):
109
110
x = np.empty(n+1)
110
111
x[0] = x0
@@ -122,10 +123,10 @@ plt.show()
122
123
123
124
To speed the function `qm` up using Numba, our first step is
124
125
125
-
```{code-cell}python3
126
-
from numba import jit
126
+
```{code-cell}ipython3
127
+
from numba import njit
127
128
128
-
qm_numba = jit(qm)
129
+
qm_numba = njit(qm)
129
130
```
130
131
131
132
The function `qm_numba` is a version of `qm` that is "targeted" for
@@ -135,7 +136,7 @@ We will explain what this means momentarily.
135
136
136
137
Let's time and compare identical function calls across these two versions, starting with the original function `qm`:
137
138
138
-
```{code-cell}python3
139
+
```{code-cell}ipython3
139
140
n = 10_000_000
140
141
141
142
qe.tic()
@@ -145,7 +146,7 @@ time1 = qe.toc()
145
146
146
147
Now let's try qm_numba
147
148
148
-
```{code-cell}python3
149
+
```{code-cell}ipython3
149
150
qe.tic()
150
151
qm_numba(0.1, int(n))
151
152
time2 = qe.toc()
@@ -156,13 +157,14 @@ This is already a massive speed gain.
156
157
In fact, the next time and all subsequent times it runs even faster as the function has been compiled and is in memory:
157
158
158
159
(qm_numba_result)=
159
-
```{code-cell} python3
160
+
161
+
```{code-cell} ipython3
160
162
qe.tic()
161
163
qm_numba(0.1, int(n))
162
164
time3 = qe.toc()
163
165
```
164
166
165
-
```{code-cell}python3
167
+
```{code-cell}ipython3
166
168
time1 / time3 # Calculate speed gain
167
169
```
168
170
@@ -194,12 +196,12 @@ Note that, if you make the call `qm(0.5, 10)` and then follow it with `qm(0.9, 2
194
196
195
197
The compiled code is then cached and recycled as required.
196
198
197
-
## Decorators and "nopython" Mode
199
+
## Decorator Notation
198
200
199
201
In the code above we created a JIT compiled version of `qm` via the call
200
202
201
-
```{code-cell}python3
202
-
qm_numba = jit(qm)
203
+
```{code-cell}ipython3
204
+
qm_numba = njit(qm)
203
205
```
204
206
205
207
In practice this would typically be done using an alternative *decorator* syntax.
@@ -208,14 +210,12 @@ In practice this would typically be done using an alternative *decorator* syntax
208
210
209
211
Let's see how this is done.
210
212
211
-
### Decorator Notation
212
-
213
-
To target a function for JIT compilation we can put `@jit` before the function definition.
213
+
To target a function for JIT compilation we can put `@njit` before the function definition.
214
214
215
215
Here's what this looks like for `qm`
216
216
217
-
```{code-cell}python3
218
-
@jit
217
+
```{code-cell}ipython3
218
+
@njit
219
219
def qm(x0, n):
220
220
x = np.empty(n+1)
221
221
x[0] = x0
@@ -224,15 +224,21 @@ def qm(x0, n):
224
224
return x
225
225
```
226
226
227
-
This is equivalent to `qm = jit(qm)`.
227
+
This is equivalent to `qm = njit(qm)`.
228
228
229
229
The following now uses the jitted version:
230
230
231
-
```{code-cell} python3
232
-
qm(0.1, 10)
231
+
```{code-cell} ipython3
232
+
%%time
233
+
234
+
qm(0.1, 100_000)
233
235
```
234
236
235
-
### Type Inference and "nopython" Mode
237
+
Numba provides several arguments for decorators to accelerate computation and cache functions [here](https://numba.readthedocs.io/en/stable/user/performance-tips.html).
238
+
239
+
In the [following lecture on parallelization](parallel), we will discuss how to use the `parallel` argument to achieve automatic parallelization.
240
+
241
+
## Type Inference
236
242
237
243
Clearly type inference is a key part of JIT compilation.
238
244
@@ -246,29 +252,83 @@ This allows it to generate native machine code, without having to call the Pytho
246
252
247
253
In such a setting, Numba will be on par with machine code from low-level languages.
248
254
249
-
When Numba cannot infer all type information, some Python objects are given generic object status and execution falls back to the Python runtime.
255
+
When Numba cannot infer all type information, it will raise an error.
250
256
251
-
When this happens, Numba provides only minor speed gains or none at all.
257
+
For example, in the case below, Numba is unable to determine the type of function `mean` when compiling the function `bootstrap`
252
258
253
-
We generally prefer to force an error when this occurs, so we know effective
0 commit comments