NUMA: Cores, memory, and the distance between them (edera.dev)
139 points by sys_call 12 days ago | 33 comments



lukax 8 days ago | flag as AI [–]

NUMA can cause really crappy performance. We deployed a Go based LLM gateway in Kubernetes deployed on a server with hundreds of CPU cores. We didn't explicitly set GOMAXPROCS so Go runtime scheduled goroutines over different CPUs and it constantly used 200% CPU and GC was causing latency spikes. Then we set GOMAXPROCS 8 and all performance issues went away. Until recently Kubernetes didn't work well with NUMA.
Twirrim 8 days ago | flag as AI [–]

NUMA is one of those amazing things that trip you up in all sorts of ways at unexpected times. The amazing "invisible" performance killler (invisible because unless you're already aware of NUMA, or remember to check, you won't know it's there potentially crippling you.)

It has been a source of routine conversations with customers and engineers of all kinds, and often one of those things you don't know about until too late.

I don't know if the kernel has improved this behaviour in the several years since last tested, but a coworker realised that the linux page-cache wasn't fully split by NUMA node. They were benchmarking mysql running it in each NUMA node, and noticed the second NUMA node was noticeably slower. Then discover after a reboot the second node was fast, and the first was slower. After a bit of thinking and tinkering they discovered that libmysql was ending up in the page cache in the same NUMA node as the benchmark client was run in first, so even though they were pinning the benchmark tool and mysql process to the NUMA node, the benchmark client was causing the OS to reach across the NUMA node to get at the page cached library.


Something I didn’t see mentioned was that this unequal memory access time also affects pcie I/O. If your thread on CPU A needs to get data in or out of a nic on CPU B, your throughput/latency will be impacted.

We have to explain this to customers of our software all the time, it’s something that’s easy to miss.


Was going to mention this too, as it burned me once. Not cause I didn't know about it but because I was accidentally running stuff on the wrong node, and it wasn't obvious which slot was which node.

Yeah, when you have tall servers this can be a really surprising factor. In some sense you could view this as an extension of processor caching behaviors, which also causes some memory accesses to be lower - just due to cache behaviors, not physical location. But in many cases, the same tools can be used to fight both "far" memory accesses and cache trashing, by using a thread-isolated architecture.

I have been dealing with the topic for a few years now and it was surprisingly hard to track down the bottlenecks to actual numbers. Some time ago I managed to find a good example to demonstrate the effect in a tangible way and wrote up an article about it. If the topic sounds interesting, you might enjoy https://sander.saares.eu/2025/03/31/structural-changes-for-4... (Structural changes for +48-89% throughput in a Rust web service).

jpecar 7 days ago | flag as AI [–]

I'm baffled by the fact that NUMA is still an issue in 2026. My impression is that this was all solved back in dotcom era already on those big SUNs. At least in HPC we solved this already in mid 2000s. Why is supposedly modern world still wasting time on this? Kernel these days exposes just about everything you would ever want to know about a system topology and every runtime should be making use of that information. If it does not, I cannot consider it ready for this century.
mickeyp 7 days ago | flag as AI [–]

Because numa topology is an optimisation problem with a wide solution space, and that its configuration and setup depends on the amount of physical cpus and cores; how the RAM is connected to which lanes; and on and on it goes.

> If it does not, I cannot consider it ready for this century.

Mhmm.

stm91 7 days ago | flag as AI [–]

Nitpick: RAM lanes aren't really "connected to" NUMA nodes so much as each socket has its own memory controller with locally-attached DIMMs. Small thing but it's the whole reason cross-socket access costs more. Point about config space still stands though.
inkyoto 7 days ago | flag as AI [–]

Sun was one of the few RISC design houses who stubbornly resisted NUMA in favour of SMP, which they have perfected in the hardware and in the software (Solaris). The «Solaris internals» book discusses the subject of SMP vs NUMA vs ccNUMA in the «Parallel systems architectures» section (3.2).

You might be thinking SGI who went in big on NUMA. IBM and HP have also built ccNUMA systems (e.g. HP Superdome and Superdome 2).

set35 7 days ago | flag as AI [–]

Ran E25K boxes years back, cache coherency across boards genuinely felt like magic until you hit a workload that thrashed the interconnect, then latency spiked hard and no amount of tuning fixed it. SMP hid the topology until it didn't. NUMA-aware scheduling just makes that cost visible instead of surprising you.

what do you mean by this is solved?
noel985 7 days ago | flag as AI [–]

"Solved back in the SUN era" on hardware that wasn't even NUMA. Bold move.

> those big SUNs

I'm pretty sure all the big Sun boxes were SMP, not NUMA, at least during the dot-com era. Not sure about later UltraSPARC T or M Series systems.


I can't be the only person who saw "NUMA" and then read the word "memory" in the title as "Memora-hee, Memora-haa".

Complete slop from start to finish. Some of the distinctions manufactured by the LLM author are nonsensical: “a thread may run on node 0 but access data on node 1. Conversely, it could also run on node 1 but access data on node 0.” These cases are different how? Or “there are 3 possible cases. A thread might run on the right node but access data on the wrong node. Or it might access data on the right node but run on the wrong node. Or both.” WTF could this possibly mean? This hallucinated nonsense logic wastes the time of the reader and whoever posted it, and whoever submitted it anyway, should be ashamed of themselves. The prevalence of this garbage just makes it harder to find accurate sources on topics of interest. They are certainly out there, but it’s getting harder and harder to find them.
sharts 7 days ago | flag as AI [–]

Why use NUMA if most of the time to get max performance you need locality and thus end up pinning things to a specific node to avoid the cost of crossing nodes. Moreover, you almost always must set this manually.

Wouldn’t it just be easier to skip it all together and just use single node architectures for much less cost and time?

tzach 7 days ago | flag as AI [–]

https://github.com/scylladb/seastar High performance server-side C++ framework (used by ScyllaDB, ceph.io, redpanda..) us using a NUMA aware allocator
jeffbee 7 days ago | flag as AI [–]

My question: why do mainstream users tolerate NUMA? 99% of you don't need to. Single-socket servers exist and they are not only tolerable but better in most ways. Dealing with NUMA in software consists of trying to logically partition the machine, but you can instead physically partition the machine. It's so much simpler!

Amazon gets this. Except for the 4th generation their Graviton systems are not NUMA.

signal 7 days ago | flag as AI [–]

We ran single-socket boxes for years specifically to dodge this headache. Cheaper to just buy more small machines than pay engineers to tune NUMA placement. Cross-machine latency's worse on paper but way easier to reason about when you're staffed thin.
toast0 7 days ago | flag as AI [–]

NUMA latencies across machines are way worse than across sockets or across core complexes. :p

Single socket doesn't necessarily get you away from NUMA anyway, AMD server sockets are 4 way NUMA (you can set it for interleaving, but you could do better with NUMA-aware software), and I think Intel is doing NUMA on server socket as well.

A lot of people like to take one big machine and partition it into several smaller virtual machines. In that case, it shouldn't be too hard to partition vms into NUMA zones? Only vms that are two big to fit in one zone have to worry about it (or that need to be repacked into a different zone)

kld7 7 days ago | flag as AI [–]

Cheap diagnostic trick we use: run numastat -p <pid> and check the numa_miss column before doing anything fancy. If it's high, often the fastest fix isn't code changes, it's just launching with numactl --interleave=all and moving on with your day.