numa aware programming

**NUMA-Aware Programming** is **the practice of structuring parallel applications to account for the non-uniform memory access costs of modern multi-socket systems — placing data in memory local to the processors that access it and scheduling threads to cores near their data, achieving 2-4× performance improvement over NUMA-oblivious approaches for memory-bandwidth-sensitive workloads**. **NUMA Architecture:** - **Multi-Socket Topology**: each CPU socket has local DRAM channels providing ~200-400 GB/s bandwidth; accessing remote DRAM on another socket traverses inter-socket links (UPI, Infinity Fabric) with 1.5-3× higher latency and reduced bandwidth - **NUMA Nodes**: each socket (or sub-socket on large processors) forms a NUMA node with its own memory controller; topology is exposed via /sys/devices/system/node on Linux and queried via hwloc or numactl - **Distance Matrix**: NUMA distances quantify relative access costs; local access = distance 10 (reference); cross-socket = distance 20-32; cross-NUMA within one socket (sub-NUMA clustering) = distance 12-16 - **Memory Interleaving**: default Linux policy interleaves pages across NUMA nodes for average-case performance; dedicated applications benefit from explicit NUMA-local allocation **Memory Allocation Policies:** - **First-Touch**: Linux default for private allocations; page is allocated on the NUMA node where the first page fault occurs — initialization thread determines placement; parallel first-touch (each thread initializes its portion) distributes pages correctly - **numactl --membind/--interleave**: command-line control of NUMA policy; --membind=N restricts allocation to node N; --interleave=0,1 distributes pages round-robin for shared data accessed by all sockets equally - **mbind/set_mempolicy**: programmatic NUMA policy control at page granularity; MPOL_BIND forces allocation on specified nodes; MPOL_PREFERRED suggests a node but falls back if memory is unavailable; MPOL_INTERLEAVE distributes evenly - **Huge Pages**: 2MB and 1GB huge pages reduce TLB misses and improve memory access predictability; NUMA-local huge page allocation requires explicit reservation (hugetlbfs) or transparent huge pages (THP) with NUMA awareness **Thread-Data Affinity:** - **CPU Pinning**: pthread_setaffinity_np or taskset binds threads to specific cores; ensuring thread i runs on the same NUMA node as its data partition eliminates cross-socket memory access - **OpenMP Affinity**: OMP_PLACES=cores and OMP_PROC_BIND=close/spread control thread placement; close packing fills one socket before using the next (good for memory-intensive, socket-local workloads); spread distributing evenly across sockets maximizes aggregate bandwidth - **Work Partitioning**: divide data arrays so that each NUMA node owns a contiguous chunk; assign threads on each node to process their local chunk; reduction operations across nodes use a two-level hierarchy (local reduce, then cross-node reduce) - **Migration Detection**: Linux AutoNUMA (NUMA balancing) periodically unmaps pages and remaps them on the accessing node when consistent cross-node access is detected — automatic but introduces TLB shootdown overhead **Performance Diagnosis:** - **perf stat -e numa-***: hardware performance counters track local vs remote memory accesses; remote access ratio >20% indicates NUMA placement issues for bandwidth-sensitive code - **numastat**: reports per-node memory allocation statistics; large numa_miss counts indicate first-touch allocation on wrong nodes — initialization pattern needs correction - **Memory Bandwidth Measurement**: STREAM benchmark per-node measures local bandwidth capacity; cross-node bandwidth is typically 30-50% of local — the NUMA penalty quantifies the optimization opportunity - **Intel VTune / AMD uProf**: visualize NUMA access patterns and identify hot data structures causing cross-socket traffic; guide data layout reorganization and thread pinning decisions NUMA-aware programming is **essential for achieving peak performance on modern multi-socket servers — the 2-3× bandwidth difference between local and remote memory access means that memory placement and thread affinity decisions have a first-order impact on application throughput, especially for memory-bandwidth-bound HPC, database, and machine learning workloads**.

Go deeper with CFSGPT

Get AI-powered deep-dives, save terms, and run advanced simulations — free account.

Create Free Account