Skrytý potenciál Raspberry Pi 4 a 5: Poznejte NUMA a zrychlete svůj systém
NUMA (Non-Uniform Memory Access) patří v serverovém světě mezi běžné zlepšováky propustnosti pamětí, kdy každý uzel CPU obsluhuje „svou“ RAM a operační systém se při plánování procesů snaží držet data co nejblíže běžícím vláknům. Na deskách velikosti kreditky byste NUMA nečekali – přesto právě emulace NUMA přináší na Raspberry Pi 4 i Pi 5 překvapivý nárůst výkonu ve více vláknech. Testy ukazují zrychlení až 46 % v Geekbenchi Multi-Core a kolem 6 % v single-thread úlohách.
NUMA a Raspberry Pi
Prakticky všechny modernější modely Raspberry Pi obsahují čtyřjádrový SoC (System on a Chip) od Broadcomu s jedním fyzickým paměťovým řadičem. NUMA emulace rozdělí jádra na logické uzly a kernel začne lépe rozkládat přístupy do cache a frontu paměťového řadiče. Výsledkem je menší „tlačenice“ při paralelním čtení/zápisu a vyšší efektivita v benchmarku i reálných compile-time/test-time scénářích.

Něco málo o tom, jak NUMA funguje
NUMA je architektura, v níž má každý procesor (či procesorový uzel) vlastní připojenou paměť. Oproti tomu v klasickém UMA (Uniform Memory Access) sdílejí všechny procesory jednu společnou paměť. Nejčastěji používaný model SMP (Symmetric Multiprocessing) je typickým příkladem UMA architektury. S NUMA se setkáme zejména na víceprocesorových základních deskách, tedy takových, které obsahují více fyzických patic pro procesory (nejde jen o více jader v jednom čipu).

Výhodou NUMA je, že každý uzel (node) má vlastní paměťový subsystém, což umožňuje rychlejší přístup k datům, pokud jsou uložená lokálně. Přitom operační systém vnímá všechna jádra i celou paměť jako jeden společný prostor.

Tato flexibilita ale přináší i nevýhodu: pokud procesor potřebuje data uložená v paměti jiného uzlu, musí je ten druhý procesor nejprve načíst a pak je přes vnitřní propojení (interconnect) přeposlat. Tento nepřímý přístup je pomalejší než čtení z vlastní paměti.
Z tohoto důvodu se operační systém snaží plánovat úlohy tak, aby měly data co nejblíže, ideálně v lokální paměti uzlu, kde běží. K tomu lze využít nástroj numactl, který umožňuje nastavovat, na jakých uzlech procesy poběží a odkud budou přistupovat do paměti.
Například dvouprocesorový server se 40 jádry může v NUMA vypadat jako dva oddělené uzly, každý s 20 jádry a vlastní částí paměti.
Informace o NUMA hardwaru
NUMA Nody | |
---|---|
Dostupné nody: | 2 nody (0-1) |
Detaily Nodu 0 | |
---|---|
CPU: | 0 1 2 3 4 5 6 7 8 9 20 21 22 23 24 25 26 27 28 29 |
Velikost paměti: | 63818 MB |
Volná paměť: | 57015 MB |
Detaily Nodu 1 | |
---|---|
CPU: | 10 11 12 13 14 15 16 17 18 19 30 31 32 33 34 35 36 37 38 39 |
Velikost paměti: | 64462 MB |
Volná paměť: | 33607 MB |
Vzdálenosti mezi nody (Node distances) | ||
---|---|---|
node 0 | node 1 | |
node 0 | 10 | 21 |
node 1 | 21 | 10 |
Aktuální NUMA nastavení
Nastavení `numactl –show` | |
---|---|
Policy: | default |
Preferred node: | current |
Physcpunind: | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
Cpubind: | 0 1 |
Nodebind: | 0 1 |
Membind: | 0 1 |
Preferred: | (prázdné – viz poznámka níže) |
Dává NUMA na Raspberry Pi vůbec smysl?
Raspberry Pi 4 i 5 sice obsahují pouze jeden čtyřjádrový procesor a paměť připojenou přes jediný paměťový řadič, takže skutečná NUMA architektura zde nedává na první pohled smysl. Proč tedy vůbec emulovat NUMA?
Někteří vývojáři upozornili na fakt, že po aktivaci tzv. fake NUMA – tedy emulace NUMA architektury – došlo u Raspberry Pi 5 k měřitelnému zlepšení výkonu. V testech Geekbench se výkon zvýšil přibližně o 6 % v jednovláknových úlohách a až o 18 % ve vícevláknových scénářích.
Klíčové však bylo použití specifického režimu interleave=all
, aktivovaného přes jádrový parametr numa_policy=interleave
. V tomto režimu se data zapisují rovnoměrně napříč všemi dostupnými „uzly“ (v tomto případě logickými, nikoli fyzickými).
Je důležité dodat, že tento přístup je u skutečných NUMA systémů (např. dvouprocesorové servery) obvykle kontraproduktivní – rozkládání zápisu do více uzlů zvyšuje latenci a zatěžuje mezipočítačové propojení (interconnect). U Raspberry Pi však díky sdílenému řadiči a zjednodušené paměťové hierarchii může mít tento režim pozitivní dopad, zejména na rozložení zátěže a využití cache.
Jak NUMA na Raspberry Pi spustit?
Postup aktivace emulace NUMA na Raspberry Pi je poměrně jednoduchý. Nejprve je potřeba aktualizovat jádro pomocí příkazu:
$ sudo rpi-update
Následně upravíte nastavení bootloaderu (příkaz pro konfiguraci EEPROM)
Arduino
$ sudo rpi-eeprom config -e
Pro Raspberry Pi 4 použijte hodnotu (konfigurace paměti config.txt)
ini
SDRAM_BANKLOW=3
Pro Raspberry Pi 5 přidejte řádek (konfigurace paměti config.txt)
ini
SDRAM_BANKLOW=1
Počet vytvořených NUMA uzlů (ve skutečnosti se jedná o rozdělení paměťových oblastí, počet jader zůstává stejný) závisí na konkrétním modelu a velikosti RAM. Například Raspberry Pi 4 s 8 GB vytváří pouze dva uzly, tatímco Raspberry Pi 5 s 8 GB RAM vytváří výchozích osm uzlů. Tato výchozí konfigurace se zatím ukazuje jako nejvhodnější.
V případě potřeby ale můžete počet uzlů upravit pomocí jádrového parametru. Například pro vytvoření čtyř uzlů přidejte do souboru
/boot/firmware/cmdline.txt
následující volbu:
ini
numa=fake=4
Na Raspberry Pi 5 s 8 GB RAM pak NUMA uzly vypadají například takto:
Informace o NUMA hardwaru (8 nodů)
Přehled NUMA nodů | |
---|---|
Dostupné nody: | 8 nodů (0-7) |
Detaily jednotlivých nodů
Uzel (Node) | CPU | Velikost paměti (MB) | Volná paměť (MB) |
---|---|---|---|
Node 0 | 0 1 2 3 | 993 MB | 948 MB |
Node 1 | 1019 MB | 992 MB | |
Node 2 | 1019 MB | 993 MB | |
Node 3 | 955 MB | 826 MB | |
Node 4 | 1019 MB | 991 MB | |
Node 5 | 1019 MB | 992 MB | |
Node 6 | 1019 MB | 993 MB | |
Node 7 | 1014 MB | 986 MB |
Vzdálenosti mezi nody (Node distances)
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
0 | 10 | 20 | 20 | 20 | 20 | 20 | 20 | 20 |
1 | 20 | 10 | 20 | 20 | 20 | 20 | 20 | 20 |
2 | 20 | 20 | 10 | 20 | 20 | 20 | 20 | 20 |
3 | 20 | 20 | 20 | 10 | 20 | 20 | 20 | 20 |
4 | 20 | 20 | 20 | 20 | 10 | 20 | 20 | 20 |
5 | 20 | 20 | 20 | 20 | 20 | 10 | 20 | 20 |
6 | 20 | 20 | 20 | 20 | 20 | 20 | 10 | 20 |
7 | 20 | 20 | 20 | 20 | 20 | 20 | 20 | 10 |
Aktuální NUMA nastavení (Policy: interleave)
Nastavení `numactl –show` | |
---|---|
Policy: | interleave |
Preferred node: | 0 (interleave next) |
Interleavemask: | 0 1 2 3 4 5 6 7 |
Interleavenode: | 0 |
Physcpunind: | 0 1 2 3 |
Cpubind: | 0 |
Nodebind: | 0 |
Membind: | 0 1 2 3 4 5 6 7 |
Preferred: | 0 1 2 3 4 5 6 7 |
1. Aktualizujte kernel – potřebujete verzi 6.6 + (součást Raspberry Pi OS Bookworm nebo novější).
2. Do souboru /boot/cmdline.txt
přidejte před „rootwait
“ parametr:
ini
numa=fake=2
Hodnota „2“ vytváří dva NUMA uzly – osvědčilo se pro Pi 4 i Pi 5. Experimentátoři uvádějí, že hodnota „4“ na Pi 5 někdy přinese ještě pár procent navíc, ale ne vždy stabilně.
3. Uložte, rebootujte a ověřte:
css
$ sudo apt install numactl
$ numactl --hardware
Výpis by měl ukázat dva NUMA nodes.
Co ukázala měření?
Výsledky testů na Raspberry Pi 4 8 GB (výchozí numa=fake=2) a Raspberry Pi 5 8 GB (výchozí numa=fake=8).
Raspberry Pi 4 8 GB | numa=fake=2
benchmark | 1 vlákno | 4 vlákna |
---|---|---|
Geekbench | 1 % | 8 % |
Stream add | -1 % | 7 % |
kompilace jádra | 4 % | |
HPL | 2 % | 4 % |
bzip3 | 9 % | 12 % |
pigz | -0 % | -6 % |
zstd | 1 % | 36 % |
xz | 2 % | 7 % |
geometrický průměr | 2 % | 8 % |
V případě Raspberry Pi 4 8 GB nejsou výsledky tak dobré, nicméně průměrně jsou jednojádrové testy o 2 % rychlejší a vícejádrové o 8 %. Možná je potřeba zvolit větší počet NUMA uzlů pomocí parametru jádra, například numa=fake=4
.
Raspberry Pi 5 8 GB | numa=fake=8
benchmark | 1 vlákno | 4 vlákna |
---|---|---|
Geekbench | 14 % | 46 % |
Stream add | -2 % | 27 % |
kompilace jádra | 11 % | |
HPL | 3 % | 25 % |
bzip3 | 29 % | 96 % |
pigz | 0 % | 28 % |
V jednovláknových úlohách jsou vybrané testy rychlejší průměrně o 16 %, ve vícevláknových o 46 %. Jednak máme ve výchozím nastavení dvakrát více uzlů (osm místo čtyř) a možná také pomohlo vylepšené časování pamětí, jak bylo výše zmíněno.
Výraznější přínos je u vícevláknových testů, tam je patrně paměť a řadič úzkým místem. Největší nárůst výkonu pozorujeme u komprese pomocí zstd a bzip3 na výchozí nastavení komprese a ve více vláknech. V případě Raspberry Pi 5 je vícevláknové zstd rychlejší dokonce o 164 %.
Benchmark | Raspberry Pi 4 | Raspberry Pi 5 | Poznámka |
Geekbench 6 (Multi-Core) | 38,00 % | 46,00 % | numa=fake=2 |
Geekbench 6 (Single-Core) | ±0 – +4 % | 6,00 % | mírný přínos díky lepšímu prefetchi |
Sysbench CPU 8 threads | 25,00 % | 31,00 % | vyšší IPC při paralelních úlohách |
(Výsledky se liší podle taktu, chlazení a SD/SSD; uvedeny jsou průměry z více testů komunity.)
Praktické dopady
- kompilace, jednotkové testy, kódování videa – všude tam, kde jádra jedou naplno, pocítíte zrychlení nejvíc
- IO-bound úlohy (NAS, databáze s výrazným diskovým přístupem) – benefitují spíše okrajově
- spotřeba – zůstává prakticky stejná; NUMA emulace je jen jiná strategie plánovače
Závěr
NUMA byla doposud doménou vícepatricových serverů. Díky malé kernelové změně a boot parametru si ale výhodu chytřejší práce s pamětí může vyzkoušet každý majitel Raspberry Pi 4 nebo 5. Pokud kompilujete, renderujete či provozujete vícevláknové kontejnery, stojí pětiminutový zásah do cmdline.txt
za pokus – uvidíte, že Pi dokáže „šlapat“ citelně rychleji.
Odkazy
Oficiální Raspberry Pi fórum.
Užitečné poznámky Jeffa Geerlinga na GitHubu.