U instrukcí je pak definováno, zda budou horní prvky registrů vynulovány, nebo ponechány na původní hodnotě. Tento koncept není úplně nový a můžeme ho vidět i u základních pracovních registrů (AL AX EAX RAX)...
Právě že ten koncept je nový a zadělal x86_64 na velké problémy. O to víc překvapující, že v případě obecných registrů (*AX) to vyřešili správně. Kvůli tomu, že původní SSE nemění horní části registrů, v důsledku dávají cílový registr do role zdrojového í cílového operandu z hlediska pipeline. Takže přechod z kódu pro AVX do kódu SSE značně limituje možnosti paralelní execution. Intel pro to vytvořil VZEROUPPER, která explicitně označí horní části (všech) registrů jako nepoužité, což ale zase znemožní uchování stavu mezi voláním funkcí (prakticky by měl být VZEROUPPER na konci každé funkce, která operuje nad rámec XMM registrů). Přitom využití je v zásadě nulové - vektorové registry se po částech nenahrávají, a když už, tak je to přes různé shuffle...
PS: U popisu VPADD* v 15. kapitole je chyba - je tam dvakrát VPADDW místo jednoho VPADDD.
Tím, že je to na x86 řešeno jsem myslel toto:
1) můžeme pracovat s dolní částí běžného pracovního registru, horní část se nebude modifikovat, vůbec o ní ani nemusíme vědět (16bitový kód v 32bitovém režimu)
2) nebo můžeme explicitně použít MOVZX popř. MOVSX. Pravda, tady to jsou jen přenosové instrukce a jinde to udělat nejde, ale přecejen máme aspoň něco.
Pravda, v 16-bitových operacích se taky nemění horní část registrů. Tohle ale vzniklo v době 386, kdy ještě Intel pipeline dependency nejspíš vůbec nepředvídal (nebo možná nepředpokládali, že by s 16-bitovými operandy vůbec někdo běžně pracoval). U 32-bitových operací už to udělali správně a jakákoliv operace vynuluje zbytek registru. U AVX z neznámého důvodu nikoliv...
Všechny AVX a AVX-512 instrukce nulujou nepoužitou část cílového vektoru. Takže to udělali správně. Nepochopitelné je, že při přechodu k AVX právě SSE instrukce nenulujou ty horní bity YMM/ZMM registrů.
Může za to asi Windows a ta jejich Win64 konvence při volání funkcí, ale spekulovat se mi nechce.
Nepochopitelné je, že při přechodu k AVX právě SSE instrukce nenulujou ty horní bity YMM/ZMM registrů.
Ano, to jsem myslel, ne AVX kód samotný (v původním příspěvku správně, v odpovědi jsem to zjednodušil). Možné vysvětlení se zdrojem přímo od Intel je v https://stackoverflow.com/questions/41819514/why-do-sse-instructions-preserve-the-upper-128-bit-of-the-ymm-registers - zjevně kompatibilita s existujícím software, resp kernel drivery. Ale ty špatné důsledky...
Rád bych upozornil na pár věcí k detekci AVX.
Jinak se může stát, že AVX i když ho CPU má není povolené v rámci OS.
Jak to vyzkoušet? Spustit virtuál, povolit jen SSE2, a provést nějakou AVX operaci (skončí to SIGILL).
20. 4. 2025, 14:58 editováno autorem komentáře