Instructor guide

Why we teach this lesson

Learners often receive a list of acceleration tools without a model for choosing among them. This module connects two distinct performance decisions: removing interpreter overhead inside a numerical kernel with Cython, and scheduling independent kernels or data chunks with Dask. Correctness and measurement remain visible throughout.

Timing

Episode

Teaching/type-along

Exercise/discussion

Total

Software setup

10 min

5 min

15 min

1. Why single-node optimization?

15 min

5 min

20 min

2. Python performance ecosystem

20 min

15 min

35 min

3. What problems fit?

15 min

10 min

25 min

4. Cython concepts and practice

40 min

30 min

70 min

5. Dask and optimization workflow

40 min

35 min

75 min

Total

140 min

100 min

240 min

The knowledge check and integrated report are included in episode 5’s exercise budget. For a longer workshop, allocate 45–60 additional minutes to a fuller performance investigation.

Teaching mode and participation

The material is designed for instructor-led, hands-on delivery in person or online, with learners working individually or in pairs. Use live type-alongs for the build and scheduler demonstrations, followed by paired prediction-and-measurement exercises.

Pending confirmation by the course owner, plan for at most 24 learners with one lead instructor and one teaching assistant. For remote delivery or a cohort with limited compiler/HPC experience, add another assistant or reduce the cohort. Confirm staffing and the learner cap before announcing a delivery.

Learner personas

  • Computational scientist: comfortable with Python and NumPy, owns a numerical workflow, and needs to accelerate a measured loop without rewriting the full application.

  • Research software engineer: maintains reusable Python software and needs to choose a maintainable boundary among native kernels, threads, processes, and Dask.

  • HPC learner moving beyond serial Python: understands basic timing and wants practical experience using the cores of one allocated node before learning multi-node programming.

The course is not aimed at learners who still need an introduction to Python syntax or at experienced Cython/Dask developers seeking distributed-cluster administration.

Hardware requirements

  • One workstation or compute node per learner or pair.

  • At least two CPU cores and 4 GB RAM; four cores and 8 GB RAM are preferable.

  • Python 3.12+, a working C compiler, and permission to compile local extensions.

  • Approximately 1 GB free storage.

On a shared HPC system, prepare an interactive job command in advance. Ask learners to stay within allocated cores and memory. The dashboard is optional; test remote port forwarding according to site policy before class.

Preparation

One day before delivery:

  1. Build the documented environment on the teaching platform.

  2. Compile content/episodes/code/integrate_cython.pyx.

  3. Run benchmark_integrate.py and all four scheduler/implementation combinations in dask_batch.py.

  4. Record typical runtimes only for pacing; do not give them to learners as expected performance.

  5. Test the documentation build and exercise paths from a clean checkout.

  6. If using an HPC system, reserve resources and provide site-specific allocation and port-forwarding instructions separately.

Teaching recommendations

Use prediction before measurement. Ask learners to predict what compilation, typing, releasing the GIL, switching schedulers, or changing task size will do. Unexpected results are useful when the class can inspect workload size, core allocation, CPU saturation, and serialization.

Pair learners for the task-size experiments so one person records configuration while the other runs commands. Require a correctness check before accepting any timing.

Typical pitfalls

Cython extension does not build

Confirm that a compiler is installed and that the active Python environment contains Cython and setuptools. Delete only generated files belonging to the failed local build, then rebuild from content/episodes/code.

Edited .pyx code appears unchanged

The extension must be rebuilt and the importing Python process restarted. Notebook kernels and long-lived interpreters retain an already imported extension.

Threads do not speed up the Python kernel

This is the expected GIL demonstration. Confirm that the workload is CPU-bound, then compare processes. For the Cython kernel, confirm that the hot loop remains inside with nogil.

Processes are unexpectedly slow

Increase useful work per task, reduce transferred data, and confirm the script uses a if __name__ == "__main__" guard. Startup costs are especially visible on platforms that spawn processes.

More workers make execution slower

Check allocation limits, task duration, memory bandwidth, and native-library thread counts. Do not exceed physical resources to force a positive result.

Dask dashboard is unavailable

Continue with timings and system monitoring. The learning outcomes do not depend on dashboard access.

Questions learners may ask

Why not always use NumPy? Use it when the operation exists and fits the algorithm. Cython is useful for specialized kernels or control flow that is awkward to express as existing vectorized operations.

Why not always use processes? Processes avoid the single-process GIL but serialize inputs/results and can duplicate memory. Threads can be better for native nogil kernels and shared arrays.

Does Dask make data fit in memory automatically? Chunked collections can operate without materializing every result simultaneously, but algorithms, chunks, and intermediates must still be designed for the memory budget.

When should we go multi-node? Only when one node cannot meet capacity or time requirements after appropriate single-node work. That transition requires separate instruction on the system, scheduler, communication, and distributed failure modes.