Skip to content

Commit a897eb8

Browse files
jstacclaude
andauthored
Improve clarity and fix errors in Numba lecture (#524)
* Improve clarity and fix errors in Numba lecture Fix typos (deficiency, JULIA, That's is, duplicate label), drop Julia from vectorization comparison (Julia uses JIT, not traditional vectorization), replace bootstrap example with clearer function iteration example, compress decorator section into a remark, add fix for global variables gotcha, remove redundant import, and add JAX cross-reference for GPU parallelization. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Fix build: replace invalid {remark} with {admonition}, fix label clash {remark} is not a valid MyST directive — use {admonition} with title "Remark" instead. Also rename (numba)= label to (numba_lecture)= to avoid ambiguity with the document name. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c0a74f0 commit a897eb8

File tree

1 file changed

+27
-71
lines changed

1 file changed

+27
-71
lines changed

lectures/numba.md

Lines changed: 27 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ kernelspec:
1111
name: python3
1212
---
1313

14-
(speed)=
14+
(numba_lecture)=
1515
```{raw} jupyter
1616
<div id="qe-notebook-header" align="right" style="text-align:right;">
1717
<a href="https://quantecon.org/" title="quantecon.org">
@@ -49,7 +49,7 @@ In an {doc}`earlier lecture <need_for_speed>` we discussed vectorization,
4949
which can improve execution speed by sending array processing operations in batch to efficient low-level code.
5050

5151
However, as {ref}`discussed in that lecture <numba-p_c_vectorization>`,
52-
traditional vectorization schemes, such as those found in MATLAB, Julia, and NumPy, have weaknesses.
52+
traditional vectorization schemes, such as those found in MATLAB and NumPy, have weaknesses.
5353

5454
* Highly memory-intensive for compound array operations
5555
* Ineffective or impossible for some algorithms.
@@ -59,16 +59,16 @@ One way to circumvent these problems is by using [Numba](https://numba.pydata.or
5959

6060
Numba compiles functions to native machine code instructions during runtime.
6161

62-
When it succeeds, Numba will be on par with machine code from low-level languages.
62+
When it succeeds, the result is performance comparable to compiled C or Fortran.
6363

6464
In addition, Numba can do other useful tricks, such as {ref}`multithreading` or
6565
interfacing with GPUs (through `numba.cuda`).
6666

67-
Numba's JIT compiler is in many ways similar to the JIT compiler in JULIA
67+
Numba's JIT compiler is in many ways similar to the JIT compiler in Julia
6868

6969
The main difference is that it is less ambitious, attempting to compile a smaller subset of the language.
7070

71-
Although this might sound like a defficiency, it is in some ways an advantage.
71+
Although this might sound like a deficiency, it is in some ways an advantage.
7272

7373
Numba is lean, easy to use, and very good at what it does.
7474

@@ -184,7 +184,7 @@ The basic idea is this:
184184
* Moreover, the types of *other variables* in `qm` *can be inferred once the input types are known*.
185185
* So the strategy of Numba and other JIT compilers is to *wait until the function is called*, and then compile.
186186

187-
That's is called "just-in-time" compilation.
187+
That is called "just-in-time" compilation.
188188

189189
Note that, if you make the call `qm(0.5, 10)` and then follow it with `qm(0.9,
190190
20)`, compilation only takes place on the first call.
@@ -193,50 +193,10 @@ This is because compiled code is cached and reused as required.
193193

194194
This is why, in the code above, `time3` is smaller than `time2`.
195195

196-
197-
198-
## Decorator Notation
199-
200-
In the code above we created a JIT compiled version of `qm` via the call
201-
202-
```{code-cell} ipython3
203-
qm_numba = jit(qm)
204-
```
205-
206-
In practice this would typically be done using an alternative *decorator* syntax.
207-
208-
(We discuss decorators in a {doc}`separate lecture <python_advanced_features>` but you can skip the details at this stage.)
209-
210-
Specifically, to target a function for JIT compilation we can put `@jit` before the function definition.
211-
212-
Here's what this looks like for `qm`
213-
214-
```{code-cell} ipython3
215-
@jit
216-
def qm(x0, n):
217-
x = np.empty(n+1)
218-
x[0] = x0
219-
for t in range(n):
220-
x[t+1] = α * x[t] * (1 - x[t])
221-
return x
222-
```
223-
224-
This is equivalent to adding `qm = jit(qm)` after the function definition.
225-
226-
The following now uses the jitted version:
227-
228-
```{code-cell} ipython3
229-
with qe.Timer(precision=4):
230-
qm(0.1, 100_000)
231-
```
232-
233-
```{code-cell} ipython3
234-
with qe.Timer(precision=4):
235-
qm(0.1, 100_000)
196+
```{admonition} Remark
197+
In practice, rather than writing `qm_numba = jit(qm)`, we use *decorator* syntax and put `@jit` before the function definition. This is equivalent to adding `qm = jit(qm)` after the definition. We use this syntax throughout the rest of the lecture. (See {doc}`python_advanced_features` for more on decorators.)
236198
```
237199

238-
Numba also provides several arguments for decorators to accelerate computation and cache functions -- see [here](https://numba.readthedocs.io/en/stable/user/performance-tips.html).
239-
240200

241201
## Type Inference
242202

@@ -253,41 +213,35 @@ This allows it to generate efficient native machine code, without having to call
253213

254214
When Numba cannot infer all type information, it will raise an error.
255215

256-
For example, in the (artificial) setting below, Numba is unable to determine the type of function `mean` when compiling the function `bootstrap`
216+
For example, in the setting below, Numba is unable to determine the type of the function `g` when compiling `iterate`
257217

258218
```{code-cell} ipython3
259219
@jit
260-
def bootstrap(data, statistics, n_resamples):
261-
bootstrap_stat = np.empty(n_resamples)
262-
n = len(data)
263-
for i in range(n_resamples):
264-
resample = np.random.choice(data, size=n, replace=True)
265-
bootstrap_stat[i] = statistics(resample)
266-
return bootstrap_stat
267-
268-
# No decorator here.
269-
def mean(data):
270-
return np.mean(data)
220+
def iterate(f, x0, n):
221+
x = x0
222+
for t in range(n):
223+
x = f(x)
224+
return x
271225
272-
data = np.array((2.3, 3.1, 4.3, 5.9, 2.1, 3.8, 2.2))
273-
n_resamples = 10
226+
# Not jitted
227+
def g(x):
228+
return np.cos(x) - 2 * np.sin(x)
274229
275230
# This code throws an error
276231
try:
277-
bootstrap(data, mean, n_resamples)
232+
iterate(g, 0.5, 100)
278233
except Exception as e:
279234
print(e)
280235
```
281236

282-
We can fix this error easily in this case by compiling `mean`.
237+
We can fix this easily by compiling `g`.
283238

284239
```{code-cell} ipython3
285240
@jit
286-
def mean(data):
287-
return np.mean(data)
241+
def g(x):
242+
return np.cos(x) - 2 * np.sin(x)
288243
289-
with qe.Timer():
290-
bootstrap(data, mean, n_resamples)
244+
iterate(g, 0.5, 100)
291245
```
292246

293247

@@ -334,6 +288,8 @@ function.
334288

335289
When Numba compiles machine code for functions, it treats global variables as constants to ensure type stability.
336290

291+
To avoid this, pass values as function arguments rather than relying on globals.
292+
337293

338294
(multithreading)=
339295
## Multithreaded Loops in Numba
@@ -363,8 +319,6 @@ distribution.
363319
Here's the code:
364320

365321
```{code-cell} ipython3
366-
from numba import jit
367-
368322
@jit
369323
def h(w, r=0.1, s=0.3, v1=0.1, v2=1.0):
370324
"""
@@ -459,7 +413,9 @@ with qe.Timer():
459413
The speed-up is significant.
460414

461415
Notice that we parallelize across households rather than over time -- updates of
462-
an individual household across time periods are inherently sequential
416+
an individual household across time periods are inherently sequential.
417+
418+
For GPU-based parallelization, see our {doc}`lectures on JAX <jax_intro>`.
463419

464420
## Exercises
465421

0 commit comments

Comments
 (0)