What problems fit Cython and Dask?¶
Objectives
Recognize workloads suited to Cython, Dask, both tools, or neither.
Identify granularity, data-sharing, and maintenance constraints before implementation.
Form a testable optimization hypothesis.
Instructor note
15 min teaching
10 min exercise
Start from the expensive work¶
Do not select a tool from the project name or data size alone. Ask what executes inside the expensive region, whether calls are independent, how much data must move, and how long one useful unit of work lasts.
Evidence |
Strong first candidate |
Why |
|---|---|---|
A specialized Python numerical loop dominates |
Cython |
Native types and operations can remove interpreter overhead |
Many independent CPU-heavy Python functions |
Dask processes |
Separate interpreters bypass the single-process GIL |
Many independent native kernels release the GIL |
Dask threads |
Threads share memory and can execute the native work concurrently |
One costly kernel is called for many independent inputs |
Cython, then Dask |
Optimize work within each call, then schedule calls across cores |
An existing NumPy/SciPy operation already implements the work |
Existing library first |
It is usually simpler and already compiled and tested |
Tiny functions or tightly coupled shared updates |
Neither initially |
Scheduling or synchronization may exceed useful work |
Cython fit¶
Cython is a good candidate when the hot region is stable, loop-heavy, numerically typed, and difficult to express with an existing optimized array operation. It is less attractive for code dominated by I/O, rapidly changing orchestration, or Python objects whose dynamic behavior must remain inside every iteration.
The maintenance cost includes a native compiler, platform-specific build products, more specialized source, and additional correctness risks from C numeric and memory semantics.
Dask fit¶
Dask is a good candidate when work can be expressed as a graph of tasks or operations on chunked arrays/tables. Tasks should contain enough work to amortize scheduling, and transferred inputs/results should fit the node’s memory and bandwidth budget.
Dask cannot turn a sequential dependency chain into parallel work, and it does not remove Python interpreter overhead inside each task.
The decision flow is a starting hypothesis, not a substitute for measurement. A workload can move through more than one branch—for example, Cython can accelerate a kernel before Dask schedules independent calls to it.
Form a hypothesis¶
Write the intended cause and observable result before implementation:
The integration loop spends most of its time executing Python numeric operations. Typing it and calling C math through Cython should reduce time while preserving the result within tolerance.
Eight integrations are independent. Once the compiled loop releases the GIL, Dask threads should execute them concurrently without process serialization.
These hypotheses can be disproved, which makes them useful.
Exercise
For each workload, choose Cython, Dask threads, Dask processes, both tools, an existing library, or “measure/restructure first.” State one reason and one measurement.
A pandas operation on a 20 MB table takes 50 ms.
A nested Python loop computes a custom recurrence for 30 seconds.
One hundred independent calls to that recurrence use different parameters.
A NumPy matrix multiplication is slow when four Dask processes run it simultaneously.
Every task updates the same shared Python dictionary.
Solution
Keep pandas unless a profile demonstrates a meaningful bottleneck; Dask overhead is unlikely to help such a small, short operation.
Cython is a strong candidate if types and semantics can become native. Verify correctness and time the kernel.
Cython can accelerate each call; Dask threads fit if the compiled loop releases the GIL, while processes remain an alternative. Measure scheduler and task-size effects.
Inspect native BLAS threads and oversubscription before adding workers. One native thread per process is a useful experiment.
Restructure toward private results and a controlled reduction before parallelizing; shared mutation creates synchronization and correctness risks.
Keypoints
Tool selection follows execution evidence, independence, granularity, and data movement.
Cython changes work inside a kernel; Dask schedules tasks or chunks.
Existing optimized libraries and algorithmic changes remain the preferred simpler solutions when they fit.
See also
Apply the decision to a native kernel in Cython concepts and practice, and keep the selection guide nearby.