pip install numba★Pulls in a matching llvmlite + NumPy.conda install -c conda-forge numbaOften the smoothest install.from numba import njit, prange★The two you'll reach for most.from numba import vectorize, guvectorize, stencilufunc / kernel decorators.from numba import cudaGPU kernels (needs a CUDA GPU).
@njit★Put it above a numeric function.def f(x): return x @ x.TPlain Python + NumPy inside.f(a) # 1st call compiles, then fast★Compilation happens on first call.@njit(cache=True)★Persist compiled code across runs.# time the SECOND callFirst call includes compile time.
@njit★=@jit(nopython=True)— full speed, or it errors.@jitNow defaults to nopython too.# Numba likes loops + NumPy + mathThat's where it wins big.@jit(forceobj=True, looplift=True)slowObject mode — barely faster than plain Python.# nopython fails? rewrite itDon't lean on object mode.
cache=True★Save compiled code to disk (skip recompile).fastmath=True★Relax IEEE-754 → lets LLVM vectorize.parallel=True★Auto-parallelize array ops &prange.nogil=TrueRelease the GIL (for Python threads).error_model="numpy"÷0 → inf/nan instead of raising.boundscheck=TrueCatch out-of-bounds — for debugging only.
from numba import njit, prange @njit(parallel=True) # ★ split across threads def colsum(A): n = A.shape[0] acc = 0.0 for i in prange(n): # ★ parallel range acc += A[i] # reduction: safe return acc # see what got parallelized: colsum.parallel_diagnostics(level=4) # nested prange → only the outer runs parallel # writing shared A[j] across threads → race!
numba.set_num_threads(4)★Cap the worker threads.numba.get_num_threads()How many are in use.NUMBA_NUM_THREADS=8Env var — set before import.numba.threading_layer()tbb·omp·workqueue.with numba.parallel_chunksize(8):Tune how iterations are chunked.
@njit # lazy: compile per arg-type★A specialization per new type combo.@njit("float64(float64, float64)")Eager — compile at import time.@njit("f8[:](i8[:, :])")Array types:[:]1-D,[:, :]2-D.@njit(["f8(f8)", "i8(i8)"])Several signatures at once.# f8=float64 i8=int64 b1=boolShort type codes.
@vectorize★Write a scalar fn; get a NumPy ufunc.def mul(x, y): return x * yAuto-broadcasts over whole arrays.@vectorize(["f8(f8, f8)"], target="parallel")★cpu·parallel·cuda.mul.reduce(a)Full ufunc methods: reduce, accumulate…
@guvectorize(["(f8[:], f8[:])"], "(n)->(n)")Generalized ufunc — operate on sub-arrays.def g(x, out): out[:] = x - x.mean()Result written to the last arg (no return).@stencil★Fixed-offset neighbor ops (filters, convolutions).def k(a): return 0.25*(a[0,1]+a[0,-1]+a[1,0]+a[-1,0])Offsets are relative to each cell.
from numba.experimental import jitclassCompiled classes …@jitclass([("x", float64[:])])… declare a typed member spec.from numba.typed import List, Dict★Numba-native list / dict.Dict.empty(key_type=int64, value_type=float64)Typed — usable inside@njit.# plain [] list → reflected, deprecatedUsetyped.List()instead.
@cuda.jit★Write a kernel in pure Python.i = cuda.grid(1)This thread's flat index.kernel[blocks, threads](d_a)★Launch: blocks × threads-per-block.d = cuda.to_device(a); d.copy_to_host()Move data to/from the device.cuda.synchronize(); cuda.is_available()Wait for the GPU · check for one.
f.inspect_types()★IR + the types Numba inferred.f.signaturesAll compiled specializations.f.py_func(x)Call the original Python (for comparison).NUMBA_DISABLE_JIT=1★Run as plain Python to debug / trace.@njit(debug=True)Line numbers & symbols for gdb.
f(x) # warm up (compile) first★Then the real timing is representative.%timeit f(x)Benchmark after the warm-up call.%timeit f.py_func(x)Compare against pure Python.@njit(cache=True)★No recompile on the next process.f.nopython_signaturesConfirm it compiled in nopython mode.
@njit(cache=True)Make this your habitual decorator.# write plain loops over NumPy arraysNumba loves loops — don't over-vectorize.+ parallel=True and prangeFor embarrassingly parallel work.+ fastmath=TrueWhen strict IEEE-754 isn't required.# pass NumPy arrays, not Python listsAnd scalars — not objects / DataFrames.# warm up once, then measureIgnore the first (compile) call.
first call is slowcompileWarm up before timing.no pandas / no objectsunsupportedNumPy arrays + scalars + math only.Python list / dictuse typedReach fornumba.typed.List / Dict.globals are frozencareCaptured at compile — pass as arguments.shared writes in prangeraceReductions are safe; shared elements aren't.