V minulém článku jsme představili novou Raspberry Pi 4B a nový Raspbian Buster. Porovnali jsme novou malinu se starším modelem a vyřešili některé problémy. V dnešním pokračování se dostaneme zase o kousek dále.
32 bitů či 64 bitů?
Když před sedmi lety vyšla první Raspberry Pi, obsahovala jednojádrový 32bitový procesor ARM1176JZF-S z rodiny ARM11, který má architekturu ARMv6Z. Stejný procesor je také ve stále prodávané Raspberry Pi Zero. Raspberry Pi 2 pak obsahovalo stále 32bitový Cortex-A7 s architekturou ARMv7-A.
Raspberry Pi 3 uvedené v roce 2016 přineslo již 64bitový procesor Cortex-A53 s architekturou ARMv8-A a stejně i nová Raspberry Pi 4 má 64bitový procesor Cortex-A72 se stejnou architekturou. Raspberry Pi Foundation se svým Raspbianem přitom chce podporovat všechny maliny, proto je zatím operační systém Raspbian pouze 32bitový.
Když ale nakouknete do /boot
, najdete tam kernel.img
pro Raspberry Pi Zero, 1 a 2, kernel7.img
pro Raspberry Pi 3 a kernel7l.img
pro Raspberry Pi 4 s LPAE kvůli adresaci více než 2 GB RAM. Také proto byla nedávno doporučena změna velikosti oddílu /boot
ze 40 MB na 256 MB.
Raspberry Pi Foundation stejně směřuje k 64bitovému Raspbianu, jen zatím neříká, kdy k tomu dojde. Pokud si ještě pamatujete přechod ze 32 bitů na 64 na architektuře x86, tak přechod byl doprovázen výrazným zvýšením výkonu. Důvodem bylo velmi málo registrů architektury x86 (jen osm 32bitových registrů), které bylo zvýšeno v x86_64 na šestnáct 64bitových registrů. Ve skutečnosti je registrů v procesoru víc a ten s nimi dělá různá kouzla kvůli zvýšení výkonu. Například aktuální architektura AMD Zen2 má interně sto osmdesát 64bitových registrů, oproti Zen, který má sto šedesát osm 64bitových registrů. Kompilátor si však musí vystačit jen s dostupnými registry dané architektury.
Oproti tomu procesory ARM mají v 32bitech patnáct 32bitových registrů a v 64bitech jednatřicet 64bitových registrů, tedy víc, než x86. Proto se při přechodu z 32 bitů na 64 na procesorech ARM nedá očekávat takové zrychlení, jaké si pamatujeme z přechodu na x86. K tomu procesory ARM mají menší vyrovnávací paměti (cache), na které nepříznivě působí zvětšení kódu při přechodu z 32 na 64 bitů.
Jádro
Co tedy potřebujeme, aby nám Raspberry Pi 3 nebo 4 běželo na 64bitech? Nejprve je třeba jádro. V podstatě stačí překompilovat oficiální jádro pro novou architekturu arm64, taktéž zvanou aarch64. Pokud si to chcete zkusit, je tu pěkný a podrobný návod od Andreie Gherzana. Potřebujete nejprve cross-kompilátor, který běží na arm a kompiluje pro aarch64. Mimochodem, v té době nebylo možné na Raspberry Pi 4 používat více než 1 GB RAM kvůli kolizi s ovladačem USB 3. Tato chyba je již opravena a paměť lze používat celou.
Druhá možnost je použít experimentální 64bitové jádro přímo od Raspberry Pi Foundation. S posledními aktualizacemi totiž najdete v /boot
i soubor kernel8.img
. Jádro je zatím experimentální a určené pro Raspberry Pi 4, i když může fungovat i na Raspberry Pi 3.
Poslední, a asi zatím asi nejlepší, možností jsou pravidelně předkompilovaná jádra zvlášť pro Raspberry Pi 3 a Raspberry Pi 4 od vývojářky Sakaki. Výhodou je, že jádra -bis mají oproti oficiálnímu jádru navíc zkompilované různé užitečné vlastnosti. Například virtualizaci KVM, komprimovaný SWAP, BFP pro firewall a BTRFS kompilované ne jako modul, proto může být oddíl /
na souborovém systému BTRFS.
Takže nějaké 64bitové jádro máme v /boot
, jak nyní jádra mezi sebou přepínat? Celkem jednoduše, napíšeme do /boot/config.txt
arm_64bit=1
, případně přímo můžeme označit i jméno souboru, například pomocí kernel=kernel8-p3.img
. Toto jméno používá Sakaki, aby se nepletlo jádro pro Pi 3 s jádrem pro Pi 4.
Když nabootujeme 64bitové jádro, můžeme klidně dál používat 32bitový user-space, například stávající Raspbian. Otestovat výkon nového jádra můžeme třeba pomocí šifry AES. Malá poznámka: bohužel ani Raspberry Pi 3 ani Raspberry Pi 4 nemají volitelné rozšíření crypto, proto je jádrem použit alespoň pomocí instrukcí NEON (povinné SIMD rozšíření ARMv8) zrychlený algoritmus AES.
cryptsetup benchmark -c aes-xts-plain64 -s 256 cryptsetup benchmark -c aes-xts-plain64 -s 512
klíč | 32 bit encrypt | 32 bit decrypt | 64 bit encrypt | 64 bit decrypt |
256 | 86 | 75 | 88 | 78 |
512 | 66 | 57 | 67 | 59 |
klíč | 32 bit encrypt | 32 bit decrypt | 64b encrypt | 64 bit decrypt |
256 | 65 | 56 | 64 | 58 |
512 | 49 | 42 | 49 | 44 |
Lehké zvýšení rychlosti tedy vidíme, ale není to nic světoborného.
User-space
Jádro tedy už máme, jak je to nyní s 64bitovým user-space? Existuje několik možností. Nejjednodušší je použít chroot v Raspbianu a do něj nainstalovat například Debian arm64. Použijeme k tomu schroot
a debootstrap
.
sudo apt install -y debootstrap schroot cat << EOF | sudo tee /etc/schroot/chroot.d/pi64 [pi64] description=VC4 arm64 testing type=directory directory=/srv/chroot/pi64 users=pi root-groups=root profile=desktop personality=linux
preserve-environment=true EOF
sudo mkdir -p /srv/chroot
sudo debootstrap --arch arm64 stable /srv/chroot/pi64 sudo schroot -c pi64 -- apt install -y sudo
schroot -c pi64 -- chmod a+w /dev/shm
schroot -c pi64
Tímto postupem dostaneme funkční chroot s aktuálním arm64 Debianem a přitom nám zůstanou všechny užitečné nástroje pro Raspberry Pi, které v sobě obsahuje Raspbian. Do chrootu se kdykoli dostanete posledním příkazem. Dále je možné využít nějaké formy virtualizace například KVM (výhoda jader od Sakaki) nebo kontejnery systemd-nspawn a LXC.
Další možností je použít například obrazy Ubuntu pro arm64. Poslední možností je Gentoo 64 bit pro Raspberry Pi 3 a 4 od již několikrát zmíněné Sakaki. Obrazy v tomto případě obsahují i přímo 64bitová jádra, včetně aktualizačního mechanizmu, kdy výchozí je instalace předkompilovaných balíčků a nemusíte tedy malinu trápit dlouhým překladem. Obraz lite je podobně jako u Raspbianu určen k minimální instalaci například serveru bez desktopu.
Šifry
Takže máme jádro i user-space v 64 bitech, jak je to teď rychlé? Zkusme otestovat šifry v user-space. Nejprve třeba ssh, výchozí šifra je rychlá chacha20-poly1305@openssh.com
, vyzkoušíme také aes256-gcm@openssh.com
. Komprese je ve výchozím stavu vypnuta. Obě maliny mají čtyři jádra, my zatížíme dvě. Jedno bude posílat a druhé přijímat.
dd if=/dev/zero bs=1M count=4096 status=progress | ssh -c $sifra localhost 'cat > /dev/null'
šifra | 32 bit | 64 bit |
chacha | 52,9 | 51,9 |
aes | 27,7 | 20,5 |
šifra | 32 bit | 64 bit |
chacha | 27,0 | 27,4 |
aes | 19,3 | 19,9 |
Výsledky vypadají velmi podobně, u Raspberry Pi 4 překvapivě poklesne výkon AES při přechodu z 32 na 64 bitů. Podíváme se raději přímo na výkon šifer v OpenSSL.
openssl speed -evp chacha20-poly1305 openssl speed -evp aes-256-gcm
šifra | 32 bit | 64 bit |
chacha | 138,2 | 266,4 |
aes | 32,3 | 23,5 |
šifra | 32 bit | 64 bit |
chacha | 96,0 | 221,3 |
aes | 24,3 | 25,8 |
Tady je situace podobná, chacha je na 64 bitech rychlejší, ale AES ne. Za tuto zvláštnost může Debian, který nepoužívá v OpenSSL rychlý algoritmus AES, protože je potenciálně méně bezpečný a používá místo něj pomalejší variantu. Naopak Raspbian používá rychlý algoritmus. V Debianu lze chování v případě AES přepnout systémovou proměnnou OPENSSL_armcap=0
, (to by kupodivu mělo vypínat instrukce NEON). Tak sice zrychlíme AES, ale zpomalíme chacha. V Raspbianu nemá tato proměnná žádný vliv.
šifra | 32 bit | 64 bit |
chacha | 138,2 | 139,5 |
aes | 32,3 | 37,5 |
šifra | 32 bit | 64 bit |
chacha | 52,9 | 51,5 |
aes | 27,7 | 27,5 |
Komprese
Větší počet registrů by mohl mít pozitivní vliv na kompresi. Přitom velikost cache naopak vliv bude mít malý, protože dat je stejně velké množství. Zkusme třeba kompresi pomocí zstd ve vysokém stupni na zdrojových kódech jádra. V obou případech je použito zstd ve verzi 1.3.8.
time zstd -q -19 -T$(nproc) linux-4.19.tar
32 bit | 64 bit | |
RPi 4 | 478,6 | 423,7 |
RPi 3+ | 728,4 | 667,1 |
Výkon tedy v 64 bitech vzroste o 9 – 13 % oproti 32 bitům. Pro zajímavost velikost programu zstd vzroste z 628 kB jen na 632 kB. Pro srovnání stejná úloha trvá na Intel Core i5–2520M (dvě jádra+HT, 2,5 GHz) 246,3 sekund.
Linpak 64bit
Výkon malin jsme v minulém díle testovali pomocí HPL, teď se podíváme, jaký bude výkon v 64 bitech. Místo OpenBLAS použijeme knihovnu blis 0.6.0. OpenBLAS má na malině v 64 bitech trochu problémy a i po jejich vyřešení je pomalejší než blis. Knihovnu blis kompilujeme jednoduše pro Cortex-A57, výsledek jede jak na Cortex-A72 (RPi4) tak i na Cortex-A53 (RPi3)
./configure -t openmp -p /home/pi/blis cortexa57 make -j4 make check make install
Podobně jako minule smažeme v /home/pi/blis/lib
soubory *.so
, abychom linkovali knihovnu staticky. Navíc je potřeba udělat ln -s libblis.a libopenblas.a
, protože HPL knihovnu blis nezná, ale openblas si rádo přilinkuje. HPL 2.3 poté kompilujeme obdobně jako minule (ani minule nebylo potřeba specifikovat CPPFLAGS)
LDFLAGS='-L/home/pi/blis/lib -fopenmp -lm' ./configure make -j4
Pro RPi3 použijeme velikost problému Ns 10000 a pro RPi4 20000. Výsledek pro 64 bitů nejvíce záleží na parametru NBs, což je velikost bloků, do kterých se úloha rozdělí. V souboru HPL.dat můžeme specifikovat více velikostí a najít tak nejvhodnější NBs s největším výkonem. Na ostatních parametrech výkon tolik nezáleží.
HPLinpack benchmark input file Innovative Computing Laboratory, University of Tennessee HPL.out output file name (if any) 6 device out (6=stdout,7=stderr,file) 1 # of problems sizes (N) 20000 Ns 15 # of NBs 32 48 64 80 96 112 128 144 160 176 192 208 224 240 256 NBs 0 PMAP process mapping (0=Row-,1=Column-major) 1 # of process grids (P x Q) 1 Ps 1 Qs 16.0 threshold 1 # of panel fact 1 PFACTs (0=left, 1=Crout, 2=Right) 1 # of recursive stopping criterium 4 NBMINs (>= 1) 1 # of panels in recursion 2 NDIVs 1 # of recursive panel fact. 2 RFACTs (0=left, 1=Crout, 2=Right) 1 # of broadcast 0 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM) 1 # of lookahead depth 0 DEPTHs (>=0) 2 SWAP (0=bin-exch,1=long,2=mix) 8 swapping threshold 0 L1 in (0=transposed,1=no-transposed) form 0 U in (0=transposed,1=no-transposed) form 1 Equilibration (0=no,1=yes) 8 memory alignment in double (> 0)
Ještě jeden rozdíl tu je oproti verzi s OpenBLAS, která sama automaticky najde počet jader na kterých se pustí. Pro verzi s blis to musíme určit ručně přes proměnnou OMP_NUM_THREADS=4
nebo BLIS_NUM_THREADS=4
.
Ns | optimální NBs | 32 bit | 64 bit | |
RPi 4B | 20000 | 208 | 11,0 | 16,3 |
RPi 3B+ | 10000 | 176 | 6,7 | 6,7 |
Vidíme, že v případě RPi 3 nedošlo k zvýšení výkonu, pravděpodobně kvůli velikosti cache. RPi 4 pak má cache o něco větší a zde pozorujeme malý nárůst.
Minule jsem zapomněl zmínit, že HPL je také dobrý test stability a opravdu jej některé RPi 3B a 3B+ občas nezvládnou a na závěr uvidíte FAILED. Není to způsobené teplotou ani zdrojem, ale zřejmě malou tolerancí napájení CPU. Jednoduché a mírné over_voltage=2
v /boot/config.txt
problém řeší. Jedna moje RPi 3B+ tento problém měla a druhá ne. Asi se to liší kus od kusu. RPi 4 by tímto problémem trpět neměly. Moje netrpí.
Rychlost SD karty A1 vs. A2
V minulém článku jsme testovali kartu SanDisk MicroSDXC 64GB Extreme A2 a zmínili jsme, že levnější varianta A1 má patrně lepší výkon. Kartu jsem koupil a přeměřil stejnou metodou a zde jsou výsledky
sekvenční čtení MB/s |
sekvenční zápis MB/s |
náhodné čtení MB/s |
náhodný zápis MB/s |
náhodné čtení IOPS |
|
RPi 4 | 44,0 | 25,2 | 8,94 | 3,88 | 2310 |
RPi 3+ | 22,6 | 19,4 | 7,37 | 3,57 | 1880 |
RPi 3+ přetaktovaná | 37,3 | 21,1 | 8,70 | 3,57 | 2170 |
sekvenční čtení MB/s |
sekvenční zápis MB/s |
náhodné čtení MB/s |
náhodný zápis MB/s |
náhodné čtení IOPS |
|
RPi 4 | 43,8 | 31,8 | 6,05 | 3,16 | 2050 |
RPi 3+ | 22,7 | 20,4 | 5,43 | 3,28 | 1730 |
RPi 3+ přetaktovaná | 37,0 | 23,2 | 6,11 | 3,31 | 1950 |
I když je v sekvenčním zápisu karta A2 rychlejší, zaostává v náhodném zápisu i v náhodném čtení a pro Raspberry Pi jsou zatím vhodnější levnější karty A1.
Firmware
Raspberry Pi 4 má nový způsob aktualizace firmware. Jestli používáte Raspbian, tak se vám pravděpodobně sám nainstaloval program rpi-eeprom-update
. Tím můžete lehce aktualizovat bootloader a firmware USB 3 čipu VL805 (minule zmiňovaná aktualizace, která snižuje spotřebu). Nyní stačí udělat:
# sudo rpi-eeprom-update -a BOOTLOADER: up-to-date CURRENT: Tue 10 Sep 2019 10:41:50 AM UTC (1568112110) LATEST: Tue 10 Sep 2019 10:41:50 AM UTC (1568112110) VL805: up-to-date CURRENT: 000137ab LATEST: 000137ab
Nový bootloader by měl umět boot ze sítě (zatím beta). Boot z USB bude následovat. Nový firmware pro VL805 má také nižší spotřebu a navíc nevykazuje problémy s rychlostí USB 3, jako minule zmiňovaná verze. Program rpi-eeprom-update
budete mít i na RPi 3 a starších, tam však nebude dělat nic.
Vypnutí signálu HDMI
Trochu překvapivě nefunguje u Raspberry Pi 4 vypnutí signálu HDMI, tedy usnutí monitoru. Místo toho jde ven pořád signál s černou obrazovkou. Vše funguje jak má u Raspberry Pi 3B+ a starších. Problém snad bude brzy vyřešen.
On the Raspberry Pi 4, setting
hdmi_blanking=1
will not cause the HDMI output to be switched off, since this feature has not yet been implemented.