numactl - NUMA CPU & Memory Binding Cheatsheet
numactl controls NUMA (Non-Uniform Memory Access) policy for processes. On multi-socket servers, memory attached to one CPU socket (node) is faster for that socket to access than memory on another node; a process bouncing between nodes pays a latency penalty. numactl lets you bind a process to specific NUMA nodes — pinning its CPUs and its memory to the same node — which can significantly improve performance for memory-bound workloads like databases and HPC jobs.
Installation
| Platform | Command |
|---|
| Debian/Ubuntu | sudo apt install numactl |
| Fedora/RHEL | sudo dnf install numactl |
| Arch Linux | sudo pacman -S numactl |
| Verify | numactl --version |
Inspecting Topology
| Command | Shows |
|---|
numactl --hardware (-H) | NUMA nodes, CPUs per node, memory per node, distances |
numactl --show (-s) | Current process’s NUMA policy |
numastat | Per-node memory allocation hit/miss stats |
lscpu | CPU-to-node mapping (NUMA node CPUs) |
# See how many NUMA nodes and which CPUs/memory belong to each
numactl --hardware
Binding a Process
| Command | Effect |
|---|
numactl --cpunodebind=0 --membind=0 ./app | Run on node 0’s CPUs and memory |
numactl -N 1 -m 1 ./app | Short form: node 1 CPUs + memory |
numactl --physcpubind=0-7 ./app | Bind to specific CPU cores |
numactl --membind=0,1 ./app | Allow memory from nodes 0 and 1 |
numactl --interleave=all ./app | Spread memory across all nodes (round-robin) |
Memory Policies
| Policy | Flag | Meaning |
|---|
| Bind | --membind=NODES | Only allocate from these nodes (fail if full) |
| Preferred | --preferred=NODE | Prefer a node, fall back if needed |
| Interleave | --interleave=NODES | Round-robin across nodes (bandwidth) |
| Local | --localalloc | Allocate on the node the thread runs on |
When to Use Which
| Goal | Policy |
|---|
| Latency-sensitive, fits in one node | --cpunodebind=N --membind=N (co-locate) |
| Bandwidth-bound, large footprint | --interleave=all |
| Mostly one node, occasional spill | --preferred=N |
| Let the kernel decide locally | --localalloc |
Common Workflows
# Pin a database to node 0 to avoid cross-node memory latency
numactl --cpunodebind=0 --membind=0 postgres -D /data
# Bandwidth-heavy analytics: interleave memory across all nodes
numactl --interleave=all ./analytics-job
# Reserve specific cores for a real-time process
numactl --physcpubind=8-15 --membind=1 ./rt-app
# Check what policy a running setup uses
numactl --show
| Tool | Role |
|---|
| numactl | Set NUMA CPU/memory policy per process |
numastat | Monitor per-node allocation efficiency |
taskset | CPU affinity (without NUMA memory policy) |
cpupower | CPU frequency/governor tuning |
kernel numa_balancing | Automatic NUMA balancing (/proc/sys/kernel) |
Pair numactl with cpupower for frequency control; use numastat to confirm your binding actually reduced cross-node misses.
Verifying the Win
# Before/after: watch numa_miss / numa_foreign drop after binding
numastat -p $(pgrep -n app)
High numa_miss / numa_foreign means memory is being served from a remote node — exactly what binding fixes.
Resources