Learning
Všechny články
Engineering27. července 2026 5 min

Většina SIMD kódu má pořád stejný tvar

Pět kroků, které z vektorizace horké smyčky dělají rutinu

SIMD není trik pro pár lidí, je to rozpoznatelný vzor

SIMD si většina lidí spojí s ručně psaným assemblerem, tabulkami intrinsiků a knihovnami jako simdutf, kam se nikdo neodvažuje sáhnout. Ta pověst je zasloužená u toho jednoho procenta případů. Zbytek je ale překvapivě krotký. Běžná vektorizovaná smyčka není magie. Je to pět kroků, které se opakují pořád stejně a po pár napsaných smyčkách je poznáš na první pohled.


Tvar, který se nemění

Vezmi horkou smyčku, která něco skenuje, porovnává, počítá nebo přepisuje prvek po prvku. Skoro každá její vektorizovaná verze má tenhle tvar:

Nejdřív rozešleš konstanty do všech lanes a připravíš vektorové akumulátory. Pak jedeš smyčkou po jednom vektoru naráz místo po jednom prvku. Uvnitř provedeš operaci paralelně přes všechny lanes. Výsledek zredukuješ nebo uložíš. A na konci dojedeš zbytek skalární smyčkou pro prvky, které se do posledního vektoru nevešly.

To je celé. Nemění se to podle algoritmu ani podle architektury. Mění se jen ta jedna operace uprostřed. Jakmile ten kostru jednou uvidíš, přestaneš číst SIMD kód jako hieroglyfy a začneš v něm hledat právě těch pět míst.


Jeden konkrétní příklad

V terminálu Ghostty se skenují dekódované codepointy a hledá se první řídicí znak C0, tedy hodnota menší nebo rovna 0xF. Skalární verze je triviální:

while (end < cps.len and cps[end] > 0xF) end += 1;

Vektorizovaná verze přidá zhruba dvanáct řádků. Za to zpracovává čtyři hodnoty naráz na ARM, osm na AVX2 a šestnáct na AVX-512. Reálný výsledek na AVX2 hardwaru byl zhruba pětinásobné zrychlení, teoretické maximum je osminásobné. Dvanáct řádků navíc za pětinásobek na cestě, kterou terminál projde u každého znaku.

Všimni si, že skalární smyčka nikam nezmizela. Zůstává tam jako ocas na zbytek. A přesně ta zbytková smyčka je tím, co drží kód přenositelný.


Proč to napsat ručně

Nabízí se otázka, proč to nenechat na kompilátoru. Odpověď je, že autovektorizace se na to spolehnout nedá. Desítky let výzkumu ukazují, že produkční kompilátory příležitosti k vektorizaci pravidelně minou. Malá změna v okolním kódu a vzor se rozpadne, aniž ti to kdokoli řekne. Ruční SIMD je delší, ale je předvídatelný. Buď tam ten vektor je, nebo není.

Přenositelnost přitom neřešíš žádnou abstrakcí. Řeší ji ta skalární zbytková smyčka. Když CPU nemá vhodnou vektorovou podporu, hlavní blok se přeskočí a ocas zpracuje celý vstup sám. Kód zůstane korektní všude, jen na slabším stroji poběží pomaleji. Grácii tady dělá fallback, ne chytrost.


Co si z toho odnést

SIMD nemusíš umět celé, stačí umět ten běžný tvar. Až příště narazíš na horkou smyčku, která skenuje, porovnává, počítá nebo transformuje pole, zkus ji přečíst jako kandidáta na těch pět kroků. Nečekej, že to za tebe udělá kompilátor. A neboj se, že rozbiješ přenositelnost, od toho je skalární ocas. Bariéra u SIMD nikdy nebyla ve složitosti kódu, ale v přesvědčení, že je to výsada specialistů. Není. Je to vzor, který se naučíš rozpoznávat.

Poslech místo čtení — 0 zdroje k načtení.