96-jader, na x86 rybník to je kolena podlamující, to je pravda.
Ale není těch 96-jader málo Antone Pavloviči když Nvidia Super Grace bude mít 144-jader V2 kdy každé má o 19% větší IPC než tento Zen 4? A podporu revolučních vektorů SVE2, které umí teoreticky až 2048-bit?
Ono ani to Bergamo se 128-jádry nebude žádnej trhák. Přece jenom ARM má mnohem našláplejší architekturu s 6xALU + 2x Branch jednotkama, zatímco Zen 4 výrazně zaostává s jeho 4x ALU + 1x Branch.
Jednooký mezi slepými králem.
No uvidíme, až tu reálně bude, Nvidia tyhle věci oznamuje dost v předstihu a pořád to tu ještě není.
Jinak revoluční vektory SVE2 "teoreticky 2048" a prakticky 128bit.
Jediné na čem tady záleží, je výkon. A ten procesor bude mít čtyři 128bitové SIMD jednotky (Neoverse V2), takže reálný výkon může být pod úrovní Zenu 2.
A) Revoluční SVE/SVE2 tu máme prakticky tyto (z rozsahu 128...2048-bit):
1) 512-bit .......... ARM Fujitsu A64FX
2) 256-bit ......... ARM Neoverse V1
3) 128-bit .......... všechny ostatní ARMy od little až po big X4 jádra
Ukaž mi x86 SIMD sadu co umí alespoň tyto 3 délky a zůstala navzájem kompatibilní. Neukážeš, protože x86 jede pořád 30 let staré fixní délky registrů. Naposledy Intel portoval BF16 a NI z AVX512 zpět do 256-bit AVX2 pro jádra Gracemont. Což je prasárna a další sub-verze AVX2 a další fragmentace. Právě proto že 256-bit verze AVX512 neexistuje. A už vůbec si může nechat zdát o 128-bit verzi AVX512, kterou by potřeboval pro Gracemont, protože ten má vnitřně 128-bit SIMD. Tohle vše má ARM s pomocí flexibilních SVE vyřešené. To je ta revoluce.
1024-bit SVE2 za dva roky? Není problém. Už teď je to kompatibilní a tvůj dnešní SW ti na tom poběží 4x rychleji.
Nedivím se, že to uživatelé x86 nechápou.
.
.
.
B) Výkon
Tady někdo zapomíná na ARM CPU-only superpočítač, v době vydání nejvýkonnější na světě, který výkonstně porazil i obří GPU Nvidia Volta. Až tohle alespoň vzdáleně dokáže x86 CPU tak dej vědět.
.
Neoverse V2 má ....... 4x 128-bit FMA
AMD Zen 4 má ........... 2x 256-bit FMA
Takže stejný max teoretický výkon když už.
Navíc při čistě obyč nevektorovém FP64 kódu bude mít V2 výhodu v teoreticky 2x větší IPC než ten Zen 4, protože má 4 vs 2 FPU jednotky.
Je zajímavé, že sis vzal jméno Kellera a straně propaguješ tu bájnou SVE. Přitom Keller se sám již několikrát vyjádřil, že je to nešťastné řešení a jejich RISC-V žádné scallable vector instrukce mít nebude. Trošku ironie, zdá se mi.
Nelži, a uveď zrdroj. Je to přesně naopak.
RVV pro RISC-V je ještě lepší než SVE od ARMu.
Já bych toho Kellera nepodceňoval. Zatím měl vždy pravdu a do čeho se pustil byla z toho pecka.
No v hodnocení RVV bych se moc neorientoval podle nějakých dojmů a zeptal bych se programátorů, který se SIMD pracujou. zatím jsem viděl na Real World Techu spíš negativnější pohledy (v tom smyslu, že to bude mít víc problémů než SVE*).
Potvrzení užitečnosti v praxi logicky ještě moc není.
Pointa je ale ta, že když tomu člověk rozumí, jako že na to potřebuje alespoň základy v assembleru, tak ví že jak SVE tak i RVV umí fungovat i ve fixním režimu. Jenom prostě nepoužiješ ty instrukce na modifikaci délky a počtu registrů jako to umí RVV a bude se to chovat jako hloupé 128-bit SSE/AVX. Ostatně i SVE2 můžeš degradovat do fixní délky.
.
To že Keller svoji reputaci a všechny prachy vsadil na RISC-V CPU je důležitější ukazatel, než všichni anonymní nýmandi z RWT, a že jich tam je. Linus Torvalds tam kdysi kritizoval ARM a teď najednou jej chválí a používá Apple M1. A to tam patří k těm nejlepším.
.
Třeba tahle prezentace nejsou žádné dojmy (mimochodem tam je poznámka že ARM má přes 1000 instrukcí a rozhodně není RISC ve smyslu jednoduchých instrukcí, naopak ARM je našláplej funkcionalitou víc než CISC akorát bez toho ohavného variabilního CISC kodování):
https://fosdem.org/2023/schedule/event/om_rvv_sve2/attachments/slides/5376/export/events/attachments/om_rvv_sve2/slides/5376/open_media_vector_length.pdf
Díky za link, Rémi Denis-Courmont je nebo aspoň byl vývojář VLC (a ffmpegu?).
Jinak když se tam podíváte, tak je tam patrná jedna věc - kód se u těchhle rozšíření ptá hardwaru na to, jakou má šířku implementace (tj. kolik bitů jsou jednotky široké, a jestli jsem si dobře všiml i na implementaci shuffle?) a podle toho se zařizuje.
Takže v reálu se toho zas tak moc nemění proti x86 - program musí dělat runtime CPU detection a podle toho volit codepath. Jenom budete mít v programu 2-3 codepathy pro SVE2 místo SSE4, AVX2 a AVX-512.
BTW zkoušel jsem si rychle gogolit jeho aktivitu v ffmpegu a první výsledek:
"[FFmpeg-devel,1/3] lavc/opusdsp: RISC-V V postfilter"
"This is optimised for a vector size of 128-bit. Or maybe it would be
more accurate to state that this is not properly optimised for larger
vector sizes, as they would work just fine with a smaller vector group
multiplier."
¨mimochodem tam je poznámka že ARM má přes 1000 instrukcí a rozhodně není RISC ve smyslu jednoduchých instrukcí"
To je rozhodně pravda. Ty rozlišení už dneska v praxi nemají smysl ale podle nich by to byl CISC - akorát s fixní délkou instrukcí (což je to rozlišení mezi x86 a ARM, které ještě dnes smysl má).
Nemáte zač.
Dnešní definice znamená spíš tohle:
- CISC = Complicated decoding
- RISC = Rapid decoding
Všechno ostatní o komplexní x86 jsou kecy od lidí co tomu vůbec nerozumí.
Máte 100% pravdu s tím zjišťováním délky a problémům s tím spojenými. Logicky i ta RVV když nastane contex-switch a OS to uprostřed výpočtu hodí na Little jádro co má jinou délku registru, tak to zhavaruje.
Dá se to ošetřit? Určitě, CPU si může nějakou instrukcí vynutit zákaz context-sw, nebo naopak detekovat CS přes přerušení, nebo speciální registr kam se dá adresa instrukce když nastane změna délky registru. Tam dáš adresu se subrutinou která to ten CS ošetří.
Ale není to ideální, je to porušení abstraktnosti mezi ISA a HW ala VLIW Itanium. ISA by měla být nezávislá na HW, jinak se právě dostává do takových sraček jako 6 verzí SSE, 3 verze AVX a 15 verzí AVX512.
Správně by to ISA měla řešit: obyč skalár instrukce + multiplikátor kolikrát se má vykonat (ta instrukce pro multiplikace by si pro další iterace automaticky načítala další hodnotu z pole hodnot/array v C++, prostě vektor). Tím SW vůbec nemusí zjišťovat šířku vnitřních SIMD jednotek, protože to nepotřebuje, protože to je čistě starost HW. Zároveň při 16-bit hodnotě multiplikace (což se do 32-bit šířky ARM instrukce vejde) to umožňuje vektory dlouhé až 65 tisíc hodnot. To by byla paráda (ta RVV se tomu snaží alespoň přiblížit). Ale hlavně to umoňuje využít efektivně HW, protože ten vektor nerozsekává na menší, ale naopak plní FPU jednotky od jedné do maxima co má CPU vnitřně. Takže je SW je kompatibilní i s CPU v mikro-kontroléru který má jen jednu obyč FPU. Geniální řešení.
A víte proč tohle nejde? Protože CPU má třeba 32 obecných registrů kam se těch 65tis hodnot pole/vektoru nevejde. Ale jde to obejít. Musel by se multiplikovat taky i Load instrukce, která by posouvala pointer o +1 s každou iterací. Taky by tam musela být i Store instrukce pro uložení vysledků. Byl by to takový mutliplikovaný blok instrukcí, což je proveditelné, prostě bude druhá multiplikační instrukce, která nastaví speciální registr pro počet instrukcí v tomto bloku a zase pro 16-bit to může být až 65 tisíc instrukcí. Nebo to vmáčknout vše do těch 16-bitů, 10-bitů pro délku vektoru 1024 (což *FP64 = 65536-bit SIMD registr ekvivalent, to by mělo stačit) a těch zbývajících 6-bitů dává 64 možností délky bloku instrukcí. Dále je problém s gather a scatter instrukcemi, ale i to je řešitelné - posouvat poiter toho gather/scatter vectoru lze posouvat tím multiplikátorem. Stejně jdou řešit i matice a více rozměrná pole. Místo obludného Intelovského AMX, které vzalo AVX512 registry, znásobilo jejich počet 16x a tím je uspořádalo do matic (oni tomu říkají Tiles). Přitom stačí jeden FP64 registr z kterého uděláš chytrým způsobem výpočet matice třeba 1000x 1000.
Jenže vracet se a měnit celý koncept se nikomu nechce. Vem si že bys tím přišel o kompatibilitu se 128-bit NEON, kdybys místo toho dal jen 32x FP64 registrů. Takže by museli podporovat obé. Intel by ztratil hůl na AMD v podobě vydávání nových SIMD, kterým musí uzpůsobovat HW což trvá roky vývoje.
IMHO se to nedělá spíš proto, že když neznám dopředu velikost vektoru, tak se mi těžko optimalizuje algoritmus tak, aby fakt byl rychlejší a na to právě je naráženo v tom RVV patchi, kde autor říká, že to bude ideálně fungovat na 128bitech a s vyšší šířkou to nemusí být ideální.
Optimalizace v assembly se dělají tak, že člověk něco napíše a pak si to testuje na rychlost na reálném CPU a zkouší, co pomůže a co škodí. Když cílí na předem nedefinovanou velikost vektoru a ne moc definové CPU, tak tohle nemůže moc udělat a výsledek může být, že to moc nevyladí nebo třeba vyladí na jedno současné jádro, ale na ostatních to bude neefektivní. To se děje i na x86, protože třeba AVX2 nebo AVX-512 kód byl laděný na Intelu dřív, než byla implementace na AMD, kde to pak nemusí být optimální nebo může dojít ke stavu, kdy AVX2 cesta je pomalejší než SSE*. S těmahle SVE a podobně se ten problém ještě zvětší. Dokážu si představit, když budou šířky vektorů 128, 256, 512, 1024 a 2048, ale když tam uděláte extrémní volnost v šířce jednotek, tak už to bude těžké kočírovat.
P.S.
A taky jee trochu problém, že SIMD není jenom o tom, udělat sčítání nebo násobení 65tisíc krát, ale taky jsou u něj důležité operace které jdou napříč těmi SIMD lanes, permutace. Ty hlavně si s tímhle nebudou moc rozumět.
23. 6. 2023, 17:36 editováno autorem komentáře
Vždyť o těch gather a scatter jsem psal. Gather a scatter jde udělat přes skalární multiplikátor úplně stejně dobře jako to násobení.
Klidně tak lze udělat 2 rozměrné pole (matice). Využívá to v podstatě stejný princip jako se v C/C++ přistupuje k array s n-dimenzemi s využitím aritmetiky s pointery. Někdy se mi zdá že neznáte ani základy programování C a neznáte rozdíl mezi předáváním proměnné poiterem, referencí a hodnotou. To je potom těžké diskutovat protože tyto úplné základy SW souvisí jak funguje strojový kod a sám CPU.
Pointa je přece ta, že s multiplikátorem nemusíš optimalizovat VŮBEC. Vektorové optimalizace jsou nutné právě protože máš pevně danou délku vektoru a řešíš jak je vektor dlouhý a jak jej rozsekat na menší. A taky jestli je tohle místo dostatečně horké aby se s optimalizací vůbec vyplatilo ztrácet čas a člověkohodiny.
S multiplikovaným skalárem krásně uděláš autovektorizaci pomocí smyčky FOR, stačí dát kompilátoru nějakou direktivu, že tento FOR je datově nezávislý a tedy paralelizovatelný a kompilátor tam vrazí multiplikační blok. Dokonce tohle může detekovat IDE nebo kompilátor sám a dělat to automaticky. Když OoO engine v CPU dokáže řešit datové závisloti za běhu programu na 6 GHz, nevím proč by to neměl umět kompilátor co na to má 1000x víc času.
V podstatě se řeší jen zda ten FOR jde paralelizovat, ale už neřešíš kolik ten vektor má prvků, protože nejsi ničím omezen (nemáš žádné 512 registry tak pro ně nemusíš nic optimalizovat). Všechny vektory delší než 2 prvky jsou jen bonus.
Je to stejná věc jako proč mít 32 architektonických GP registrů v ISA, když CPU má fyzicky stejně třeba 250 a pracuje převážně se zásobníkem a provádí eliminaci zbytečných Load-store párů a v podstatě mraky omezení ISA chytře obchází. Jenže bohužel zatímco ty fyzické registry řeší automaticky OoO, tak ty pitomé AVX512 se musí optimalizovat ručně. A to je ten průser plynoucí z porušení abstraktnosti.
Fixní vektorové registry = VLIW Itanium se všemi problémy
1) Teoreticky vysoký paralelní výkon (proto i GPU jsou VLIW).
2) Prakticky to brutálně závisí na kompilátoru a ruční optimalizaci a plný výkon se ve skutečnosti využije málokdy (proto GPU má super výkon, ale dej tomu pár IFů a skalární výpočet a výkon padne o několik řádů, což u grafických dat nehrozí, proto se to tam vyplatí, ale většina obecných algoritmů využije AVX512 jen málokdy. Zkus si v BIOSu vypnout AVX512 jestli při běžné práci a browsení po webu poznáš rozdíl, myslím že ani náhodou). Proto AMD i Intel valí AVX512 ve skutečnosti jako 256-bit vektory což má mnohem větší využitelnost i pro AVX2.
Proto si myslím že ARM hodil zpátečku s vektory i na tom Neoverse V2 jádře. Vysoký skalární výkon se 4x128-bit a přitom paralelní výkon z toho dostanou díky OoO stejný jako z AVX512.
A v čem je rozdíl?
Shuffle akorát vyzobává hodnoty vertikálně/diagonálně z několika různých registrů místo vyzobávání hodnot z jednoho registru (horizontálně, jako to dělá gather/scatter). Vždyť je to stejný princip.
Všechny akorát dělají vektorový ekvivalent skalární instrukce MOV. Akorát kvůli registrům je to celé zbytečně komplikované. Ve skutečnosti CPU stejně dělá renaming na fyzických registrech a žádné data nepřesouvá. Stejně jako v C/C++ když přesouváš data, tak to děláš přes pole pointerů, ale ve skutečnosti data samotná se nehnou ani o bit.
24. 6. 2023, 14:25 editováno autorem komentáře
Akorát... shuffle a instrukce tohohle typu jsou to, co umožňuje dělat složitější algoritmy než "65000× vynásobit". Když potřebuju, aby se ty výpočty neděly jenom v rámci jednotlivých pruhů, ale aby se ty hodnoty nějak přemísťovaly. V multimediálním kódu typu video jsou dost stěžejní, například tahle instrukce je hodně důležitá a užitečná: https://www.chessprogramming.org/SSSE3#PSHUFB
Akorát když se to dělá přes skalární FPU, tak na to nepotřebuješ žádnou speciální Shuffle instrukci. Prostě si pointerem sáhneš přímo do pole pro jakoukoliv hodnotu i bez Shuffle.
Tady vidíš kolik zbytečných instrukcí sebou ty SIMD nesou, jenom aby měli stejnou funkcionalitu jako obyč skalár FPU výpočet. Když u AVX změníš délku registru tak musíš automaticky mít i nové instrukce, protože je to fixní, že jo. Tohle je jedna výhod SVE2, jinak by museli mít 16 verzí instrukcí pro těch 16 různých délek vektorů (třeba 384-bit nebo 640-bit ...).