NUMA pro Raspberry Pi 4 a 5 přináší vyšší výkon ve více vláknech

14. 11. 2024
Doba čtení: 6 minut

Sdílet

Zavedení emulace NUMA zvyšuje výkon u Raspberry Pi 4 a 5 průměrně až o 46 % ve vícevláknových úlohách. Použití emulace NUMA dokáže patrně lépe využít paměťový řadič v SoC Broadcom nebo paměť samotnou. Povíme si, jak emulaci NUMA vyzkoušet a otestovat.

Co je NUMA?

NUMA je zkratka pro Non-uniform memory access a jde o architekturu, kdy každý procesor obsluhuje jen svoji paměť. Na rozdíl od toho UMA (Uniform memory access) mají všechny procesory paměť jen jednu – sdílenou. Nejrozšířenější SMP (Symmetric multiprocessing) je podmnožinou UMA. Dodejme, že NUMA najdeme kupříkladu na víceprocesorových deskách (myšleno více fyzických patic, ne více jader v jednom procesoru).

Architektura NUMA s dvěma uzly

Autor: J. Fikar s využitím Depositphotos

Architektura UMA

Autor: J. Fikar s využitím Depositphotos

NUMA může mít obecně rychlejší přístup do paměti, jelikož paměti jednotlivých uzlů (nodes) jsou nezávislé. Přitom samotný systém vidí všechna jádra všech procesorů a také celou paměť jako jeden celek. Tím se dostáváme k nevýhodě NUMA: Když data pro procesor 0 budou v paměti obsluhované procesorem 1, musí data z paměti nejprve přečíst procesor 1 a poté je interconnectem poslat do procesoru 0. To je samozřejmě pomalejší, než kdyby se četlo z lokální paměti.

Příklad NUMA: dvouprocesorová deska HP Z820

Autor: Jud McCranie, podle licence: CC BY-SA 4.0

Proto systém o rozložení uzlů a paměti ví a snaží se data držet v lokální paměti. K obsluze NUMA se využívá nástroje numactl. Například dvouprocesorový počítač se 40 jádry vypadá takto:

$ numactl --hardware
available: 2 nodes (0-1)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 20 21 22 23 24 25 26 27 28 29
node 0 size: 63818 MB
node 0 free: 57015 MB
node 1 cpus: 10 11 12 13 14 15 16 17 18 19 30 31 32 33 34 35 36 37 38 39
node 1 size: 64462 MB
node 1 free: 33607 MB
node distances:
node   0   1
  0:  10  21
  1:  21  10
$ numactl --show
policy: default
preferred node: current
physcpubind: 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:

Všimneme si policy: default a také node distances, kdy pro komunikaci 0 a 1 je nastaveno 21, kdežto třeba pro 0 a 0 je to 10.

Proč NUMA na Raspberry Pi?

Raspberry Pi 4 a 5 však mají jen jeden čtyřjádrový procesor a paměť připojenou k procesoru jen jedním řadičem, proč tedy zde používáme NUMA? Letos v červnu si Tvrtko Ursulin z Igalia všiml, že možná trochu nelogicky po zapnutí emulace NUMA (fake NUMA) je výkon Raspberry Pi 5 v testu  Geekbench lepší o 6 % pro jednovláknové úlohy a  o 18 % pro vícevláknové.

Jen bylo potřeba použít NUMA interleave=all (pomocí parametru jádra numa_policy=interleave), což v praxi znamená, že se zároveň zapisuje prokládaně do paměti všech dostupných uzlů. Tady jen poznamenám, že interleave=all u normální NUMA architektury, jako byl třeba příklad dvouprocesorové desky v předchozí kapitole, povede téměř vždy ke zhoršení výkonu, protože místo použití lokální paměti se bude prokládaně využívat paměť všech uzlů, což vede k horší latenci a navíc se může přetížit interconnect.

Nápad se zalíbil vývojářům z Raspberry a ti se začali fake NUMA zabývat pro Raspberry Pi 4 a 5. Proč ne pro Raspberry Pi 3? Zřejmě proto, že na něm není možné kvůli nedostatku paměti (maximálně 1 GB) pustit Geekbench. Ten vyžaduje více než 2 GB RAM. Anebo to bude kvůli detailům organizace paměti (single rank / dual rank). Ve výchozím stavu nebude NUMA zapnutá ani na Raspberry Pi 4 s 1 a 2 GB RAM.

Vysvětlení, proč fake NUMA pomáhá s výkonem obzvláště vícevláknových aplikací, je patrně v řadiči paměti, který Broadcom v SoC pro Raspberry Pi 4 a 5 používá, nebo v paměti samotné. Rozdělení paměti na několik oblastí společně s použitím interleave pak lépe využije paměťový čip, kterému lépe svědčí zápisy a čtení daleko od sebe než blízko u sebe.

Raspberry Pi 5 s 4 GB rychlejší než s 8 GB?

Zde uděláme malou, ale zajímavou odbočku. Uživatel Brunnis před rokem zjistil, že Raspberry Pi 5 s 4 GB RAM je překvapivě rychlejší než Raspberry Pi 5 s 8 GB RAM, a to asi o 8 % ve vícejádrovém Geekbench 5. Ten mají mimochodem vývojáři Raspberry Pi celkem v oblibě, i když Linus Torvalds moc ne.

Nesporná výhoda Geekbench je v tom, že existuje pro Linux (x86, Arm64 i RISC-V), Windows, macOS, Android i iOS. V případě Raspberry Pi si tedy můžete lehce zkusit, jestli má procesor rychlejší než ten, co máte v mobilním telefonu s Androidem.

Problém byl patrně s nutným obnovováním DRAM paměti podle JEDEC. Větší paměť vyžaduje delší obnovování. Experimentálně bylo možné nastavit i na 8GB verzi obnovovací parametry 4GB verze. Dále se zjistilo, že je možné ještě zkrátit obnovovací parametry, pokud je teplota paměťového čipu dostatečně nízká.

Nakonec se po diskusi s dodavatelem RAM (Micron) zjistilo, že je možné použít ještě rychlejší obnovovací parametry pro oba paměťové čipy 4 GB a 8 GB, než dovoloval standard JEDEC. Podobné zlepšení bylo také použito pro Raspberry Pi 4. Pokud aktualizujete, měli byste tedy mít rychlejší jak Raspberry Pi 5, tak i Raspberry Pi 4. Zároveň je Raspberry Pi 5 se 4 GB a 8 GB nyní stejně rychlé. V dlouhé diskusi na GitHubu se také řešilo NUMA a zjistilo se, že významně pomáhá výkonu.

Můžu si NUMA zkusit?

Ano, vývojáři to patrně myslí s NUMA vážně a je možné si to na Raspberry Pi 4 a 5 vyzkoušet, vyladit pro svoji aplikaci a nahlásit případné problémy. Postup je jednoduchý. Aktualizujete jádro pomocí sudo rpi-update. Navíc je potřeba jen přidat řádek do nastavení boot loaderu sudo rpi-eeprom-config -e. Pro Raspberry Pi 5 tam dáte SDRAM_BANKLOW=1 a pro Raspberry Pi 4 tam dáte  SDRAM_BANKLOW=3.

Počet NUMA uzlů (vlastně jen oblastí v paměti, jádra budete mít pořád čtyři) pak závisí na modelu a na paměti. Raspberry Pi 5 s 8 GB má ve výchozím nastavení uzlů osm a Raspberry Pi 4 s 8 GB jen dva uzly. Toto nastavení se zatím jeví vývojářům jako optimální. Je ale možné, že pro vaši zátěž bude výhodnější počet uzlů změnit. Slouží k tomu parametr jádra například numa=fake=4, který napíšete do  /boot/firmware/cmdline.txt.

Na Raspberry Pi 5 8 GB pak NUMA uzly vypadají následovně:

$ numactl --hardware
available: 8 nodes (0-7)
node 0 cpus: 0 1 2 3
node 0 size: 993 MB
node 0 free: 948 MB
node 1 cpus:
node 1 size: 1019 MB
node 1 free: 992 MB
node 2 cpus:
node 2 size: 1019 MB
node 2 free: 993 MB
node 3 cpus:
node 3 size: 955 MB
node 3 free: 926 MB
node 4 cpus:
node 4 size: 1019 MB
node 4 free: 991 MB
node 5 cpus:
node 5 size: 1019 MB
node 5 free: 992 MB
node 6 cpus:
node 6 size: 1019 MB
node 6 free: 993 MB
node 7 cpus:
node 7 size: 1014 MB
node 7 free: 986 MB
node distances:
node   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
$numactl --show
policy: interleave
preferred node: 0 (interleave next)
interleavemask: 0 1 2 3 4 5 6 7
interleavenode: 0
physcpubind: 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

Všimneme si, že jednotlivé uzly nemají přesně stejně velkou paměť a také již zmiňované  policy: interleave.

Jak je to rychlé?

Sám jsem udělal několik testů na Raspberry Pi 5 8 GB (výchozí numa=fake=8) a Raspberry Pi 4 8 GB (výchozí numa=fake=2) a výsledky jsou potěšující.

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 %
zstd +71 % +164 %
xz +10 % +21 %
 geometrický průměr +16 % +46 %

V jednovláknových úlohách jsou vybrané testy rychlejší průměrně o 16 % rychlejší, ve vícevláknových o 46 %. Všimněte si, že nárůst výkonu v Geekbench je o dost vyšší, než původně hlásil Tvrtko. 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.

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.

Výraznější přínos je u vícevláknových testů, tam je patrně paměť a řadič úzkým hrdlem. 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 %.

Rychlejší Raspberry Pi 4 a 5 pro všechny

Vývojáři nechají uživatelé NUMA nějakou chvíli testovat. Problémy by mohly způsobovat například různé periférie, jako jsou kamery nebo dekodér videa h264/hevc v Raspberry Pi 4. Pokud testování dopadne dobře, změna se časem dostane do stabilního jádra v distribuci Raspberry Pi OS (dříve Raspbian) a ze zrychlení budou moci profitovat všichni uživatelé. 

bitcoin_skoleni

Uživatelé Raspberry Pi 4 s 1 a 2 GB RAM budou mít sice NUMA ve výchozím stavu patrně vypnuté, jako je tomu nyní, mohou si však NUMA ručně zapnout.

Zvýšení výkonu je patrnější u Raspberry Pi 5. Pokud máte Raspberry Pi 4, můžete experimentovat se zvýšením počtu NUMA uzlů.

Autor článku

První linux nainstaloval kolem roku 1994 a u něj zůstal. Později vystudoval fyziku a získal doktorát.