skills/allocators/numa-programming/SKILL.md
NUMA programming skill for multi-socket memory locality. Use when detecting NUMA topology, binding processes with numactl, using libnuma API, building NUMA-aware data structures, or measuring remote access penalties. Activates on queries about numactl, libnuma, NUMA topology, mbind, lstopo, or remote memory access.
npx skillsauth add mohitmishra786/low-level-dev-skills numa-programmingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Guide agents through NUMA-aware programming: topology detection with numactl and sysfs, libnuma API (numa_alloc_onnode, mbind, set_mempolicy), process binding with numactl, NUMA-aware data structures, remote access diagnosis with perf stat, and lstopo visualization.
# Hardware topology summary
numactl --hardware
# Detailed topology with distances
lstopo --of console
# sysfs nodes
ls /sys/devices/system/node/
cat /sys/devices/system/node/node0/meminfo
cat /sys/devices/system/node/node0/cpulist
Typical output:
available: 2 nodes (0-1)
node 0 cpus: 0-15
node 0 size: 65536 MB
node 1 cpus: 16-31
node 1 size: 65536 MB
node distances:
node 0 1
0: 10 21
1: 21 10
Distance 10 = local, higher = remote (cross-socket).
# Bind to node 0 CPUs and memory
numactl --cpunodebind=0 --membind=0 ./myapp
# Interleave memory across all nodes
numactl --interleave=all ./myapp
# Preferred node (fallback if full)
numactl --preferred=0 ./myapp
# Show process NUMA policy
numactl --show
cat /proc/self/numa_maps
#include <numa.h>
#include <numaif.h>
#include <stdio.h>
int main(void) {
if (numa_available() < 0) {
fprintf(stderr, "NUMA not available\n");
return 1;
}
int node = numa_node_of_cpu(0);
printf("CPU 0 on node %d\n", node);
// Allocate on specific node
size_t size = 1024 * 1024 * 1024;
void *mem = numa_alloc_onnode(size, 0);
if (!mem) return 1;
// Bind existing memory
unsigned long nodemask = 1UL << 0;
mbind(mem, size, MPOL_BIND, &nodemask, sizeof(nodemask) * 8, 0);
numa_free(mem, size);
return 0;
}
gcc -o numa_test numa_test.c -lnuma
| API | Purpose |
|-----|---------|
| numa_alloc_onnode | Allocate on specific node |
| numa_alloc_local | Allocate on current CPU's node |
| mbind | Set policy on existing mapping |
| set_mempolicy | Default policy for subsequent allocs |
| move_pages | Migrate pages to target node |
// Per-node freelist — avoids cross-node synchronization
#define MAX_NODES 8
struct per_node_pool {
void *free_list[MAX_NODES];
int node_count;
};
void *pool_alloc_numa(struct per_node_pool *p) {
int node = numa_node_of_cpu(sched_getcpu());
void *blk = p->free_list[node];
if (blk) {
p->free_list[node] = *(void **)blk;
return blk;
}
return numa_alloc_onnode(BLOCK_SIZE, node);
}
Pin threads to cores on the same node as their pool.
# Pin thread 0 to CPU 0 (node 0), allocate on node 0
numactl --cpunodebind=0 --membind=0 ./worker --id 0
numactl --cpunodebind=1 --membind=1 ./worker --id 1
#include <pthread.h>
#include <sched.h>
cpu_set_t cpuset;
CPU_ZERO(&cpuset);
CPU_SET(target_cpu, &cpuset);
pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
# Cache misses often spike with remote memory
perf stat -e cache-misses,cache-references,node-load-misses \
numactl --cpunodebind=0 --membind=1 ./myapp
# Compare local vs remote binding
perf stat numactl --cpunodebind=0 --membind=0 ./myapp
perf stat numactl --cpunodebind=0 --membind=1 ./myapp
# NUMA hit/miss stats (if available)
perf stat -e node-loads,node-load-misses,node-stores ./myapp
// Microbenchmark: touch 1GB on local vs remote node
clock_t start = clock();
for (size_t i = 0; i < size; i += 4096)
sum += ((char *)mem)[i];
Expect 1.5–3x slowdown for remote access depending on interconnect (QPI/UPI/Infinity Fabric).
# Graphical (if X11)
lstopo
# Text with memory/PCI
lstopo --of ascii
# Export for documentation
lstopo file.png
Shows: NUMA nodes, cores, caches, PCI devices — essential for DPDK NIC placement.
Poor scaling on multi-socket?
├── Check numactl --hardware
├── Verify thread and memory on same node
├── perf stat node-load-misses
├── Remote misses high?
│ ├── numactl --membind=local
│ └── Per-node data partitioning
└── Still slow → memory bandwidth bound; reduce sharing
| Symptom | Cause | Fix |
|---------|-------|-----|
| OOM on one node despite free RAM elsewhere | MPOL_BIND too strict | Use --preferred or interleave |
| 2x slower after scaling threads | Remote memory access | numactl --membind matching CPU node |
| Inconsistent benchmark results | OS migrated pages | mbind MPOL_BIND; mlock if needed |
| DPDK NIC on wrong socket | PCI far from CPU | lstopo; bind EAL to local socket |
| libnuma not found | Package not installed | apt install libnuma-dev |
| First-touch policy surprise | Alloc on node 0, run on node 1 | Allocate from bound thread |
skills/allocators/custom-allocators — per-node pool allocatorsskills/async-io/dpdk — rte_malloc_socket, NIC NUMA localityskills/hpc/mpi — MPI process binding per NUMA nodeskills/profilers/hardware-counters — cache miss measurementskills/profilers/linux-perf — perf NUMA eventsskills/low-level-programming/cpu-cache-opt — cache locality fundamentalsdevelopment
QEMU/KVM skill for virtualization and kernel development. Use when running qemu-system-x86_64 with KVM, configuring virtio devices, VFIO passthrough, QMP monitor, libvirt, or booting custom kernels. Activates on queries about QEMU, KVM, virtio, VFIO, virsh, virt-install, or -kernel -append.
development
Hardware virtualization internals skill for Intel VT-x and AMD-V. Use when studying VMCS/VMCB, EPT/NPT page tables, VMEXIT handling, APIC virtualization, or building minimal hypervisors. Activates on queries about VMX, SVM, VMCS, EPT, NPT, VMEXIT, or type-1 hypervisor.
testing
Linux containers internals skill for namespaces, cgroups, and OCI. Use when understanding clone/unshare namespaces, cgroups v2 limits, overlayfs, runc, seccomp profiles, capabilities, or escape mitigations. Activates on queries about namespaces, cgroups, overlayfs, runc, seccomp-bpf, OCI spec, or container escape.
tools
Reverse engineering skill for binary analysis. Use when decompiling with Ghidra, analyzing with radare2, scripting RE tools, triaging with strings/file/xxd, or diffing binaries. Activates on queries about Ghidra, radare2, r2, decompiler, Binary Ninja, Diaphora, or stripped binary analysis.