WebHU - Programozási kérdések és válaszok

Az AVX-SSE (VEX) átmeneti büntetések elkerülése

64 bites alkalmazásunk sok kódot tartalmaz (többek között szabványos könyvtárakban), amelyek SSE módban xmm0-xmm7 regisztereket használnak.

Gyors memóriamásolást szeretnék megvalósítani ymm regiszterekkel. Nem tudom módosítani az összes kódot, amely xmm regisztereket használ a VEX előtag hozzáadásához, és úgy gondolom, hogy ez nem praktikus, mivel növeli a kód méretét, és lelassíthatja a futását, mivel a CPU-nak nagyobb utasításokat kell dekódolnia .

Csupán két ymm regisztert (és esetleg zmm-t - az ígéretek szerint még idén elérhetővé válnak a zmm-t támogató megfizethető processzorok) szeretnék használni a gyors memóriamásoláshoz.

A kérdés a következő: hogyan kell használni az ymm regisztereket, de elkerülni az átmeneti büntetéseket?

A büntetés akkor következik be, ha csak ymm8-ymm15 regisztereket használok (nem ymm0-ymm7)? Az SSE-nek eredetileg nyolc 128 bites regisztere volt (xmm0-xmm7), de 64 bites módban (xmm8-xmm15) is elérhetők a nem VEX előtagú utasításokhoz. Átnéztem azonban a 64 bites alkalmazásunkat, és csak xmm0-xmm7-et használ, mivel van 32 bites verziója is, majdnem ugyanazzal a kóddal. A büntetés csak akkor következik be, ha a CPU valójában egy xmm regisztert próbál használni, amelyet korábban ymm-ként használtak, és amelynek egyike magasabb, 128 bites, nem nulla? Nem jobb az általam használt ymm regisztereket nullázni a gyors memóriamásolás után? Például egyszer egy ymm regisztert használtam 32 bájt memória másolására – mi a leggyorsabb módja annak nullázásának? Elég gyors a "vpxor ymm15, ymm15, ymm15"? (AFAIK, a vpxor a 3 ALU végrehajtási port bármelyikén végrehajtható, p0/p1/p5, míg a vxorpd csak p5-ön). Nem lenne itt az ideje nullázni, mint amennyit csak 32 bájt memória másolására használnánk?



Válaszok:


1

Egy másik lehetőség a zmm16 - zmm31 regiszterek használata. Ezeknek a regisztereknek nincs nem VEX megfelelője. Nincs állapotátmenet és nincs büntetés a zmm16 - zmm31 nem VEX SSE kóddal való keveréséért. Ezek az 512 bites regiszterek csak 64 bites módban és csak AVX512-vel rendelkező processzorokon érhetők el.

08.02.2019
  • Köszönöm! Láttam, hogy zmm16-ot használtál a fillchar (memset) megvalósításában. Jó ötlet! 02.05.2019

  • 2

    Az optimális megoldás valószínűleg az összes kód újrafordítása VEX előtagokkal. A VEX kódolású utasítások többnyire ugyanolyan méretűek, mint ugyanazon utasítások nem VEX verziói, mivel a nem VEX utasítások sok előtagot és escape kódot hordoznak (a rövidlátó javítások hosszú története miatt az utasításokban kódolási séma). A VEX előtag egyesíti az összes régi előtagot és escape kódot egyetlen, két vagy három bájtos előtagban (az AVX512 esetében négy bájtos).

    A VEX/nem VEX átmenet különböző módon működik a különböző processzorokon (lásd: Miért 6-szor lassabb ez az SSE-kód VZEROUPPER nélkül a Skylake-en?):

    Régebbi Intel processzorok: A VZEROUPPER utasítás a processzor különböző belső állapotai közötti tiszta átmenethez szükséges.

    Intel Skylake vagy újabb processzorokon: A VZEROUPPER azért szükséges, hogy elkerüljük a nem VEX utasítások hamis függőségét a regiszter felső részétől.

    A jelenlegi AMD processzorokon: A 256 bites regiszter két 128 bites regiszterként kezelendő. A VZEROUPPER nem szükséges, kivéve az Intel processzorokkal való kompatibilitást. A VZEROUPPER ára körülbelül 6 óraciklus.

    A VEX előtagok használatának előnye az összes utasításban, hogy elkerüli ezeket az átállási költségeket minden processzornál. A régi kód valószínűleg hasznot húzhat néhány 256 bites műveletből itt-ott a forró legbelső hurokban.

    A VEX előtagok hátránya, hogy a kód nem kompatibilis a régi processzorokkal, ezért előfordulhat, hogy meg kell őriznie a régi verziót a régi processzorokon való futtatáshoz

    11.05.2017
  • Úgy érted, hogy a VZEROUPPER ára körülbelül 6 órajel az AMD-n? Vagy Intelen? Vagy valamelyik processzoron? Jelenleg nem tudjuk az összes kódot újrafordítani VEX-be, mert kódnaplókat használunk, mind a Delphi szabványos könyvtáraiban, mind az általunk használt harmadik féltől származó könyvtárakban sok soron belüli assembler kód található, amelyek MMX/SSE-t használnak, és nem vagyunk hajlandók módosítsa ezt a kódot. 11.05.2017

  • 3

    Az összes architektúra büntetéseinek elkerülése érdekében csak ki kell adnia a vzeroall vagy vzeroupper jelet a kód VEX-kódolású utasításokat használó része után, mielőtt visszatérne a kód többi részéhez, amely nem VEX utasításokat használ.

    Ezeknek az utasításoknak a kiadása egyébként minden AVX-et használó rutin bevált gyakorlatának számít, és olcsó – kivéve talán a Knights Landing, de kétlem, hogy ezt az architektúrát használja. Még ha igen is, a teljesítményjellemzők egészen eltérnek az asztali/Xeon családétól, így valószínűleg mindenképp szükség lesz egy külön fordításra.

    Ezek az egyetlen utasítások, amelyek a piszkos felső állapotból a tiszta felső állapotba kerülnek. Nem lehet egyszerűen nullázni a használt regisztereket, mivel a chip nem követi nyomon a szennyezett állapotot regiszterenként.

    Ezeknek a vzero* utasításoknak a költsége néhány ciklus: tehát ha bármit is csinálsz az AVX-ben, megéri, akkor általában megéri kifizetni ezt a kis költséget.

    10.05.2017

    4

    Tapasztalataim szerint a Avoiding AVX-SSE (VEX) Transition Penalties legjobb módja az, ha a fordítóprogram a mikroarchitektúra natív kódját használja. Például használhatja a SSE-Intrinsics jelet a AVX-Intrinsics mellett, és használhatja a -march=native jelet. Az én GCC 6.2 lefordítja a programot és VEX-Encoded utasításokat használ. Ha látja a generált összeállítást, egy extra v-t fog találni az összes SSE lefordított kód előtt. Másrészt, ha kétségei vannak, használhatja a program __asm__ __volatile__ ( "vzeroupper" : : : ); minden pontját a ymm regiszterek használata után, de óvatosnak kell lennie.

    09.06.2017

    5

    Találtam egy érdeklődő feljegyzést Agnertől egy Intel fórumon a következő címen: https://software.intel.com/en-us/forums/intel-isa-extensions/topic/704023

    Arra a kérdésre ad választ, hogy mi történik, ha csak az ymm8-ymm9-et használom, miközben az alkalmazás xmm0-xmm7-et használ, tehát különböző regisztereket használunk.

    Íme az idézet.

    Most végeztem még néhány kísérletet egy Haswell-en. Minden vektorregisztert piszkos felső feleként kezel, ha csak egy ymm regisztert érintett meg. Más szóval, ha módosítja az ymm1-et, akkor az xmm2-re írt nem VEX utasítás hamis függése az xmm2 előző értékétől. A Knights Landingnek nincs ilyen hamis függősége. Talán az egyes regiszterek állapotára külön emlékszik?

    Remélhetőleg a jövőbeli Intel processzorok vagy külön emlékeznek az egyes regiszterek állapotára, vagy legalább külön kezelik a zmm16-zmm31-et, hogy ne szennyezzék az xmm0-xmm15-öt. Tudsz erről valamit elárulni?

    Ez a 2016. 12. 28-i válasz válasz nélkül maradt.

    A VZEROUPPER-ről is volt néhány érdekes információ Agnger blogjában: http://www.agner.org/optimize/blog/read.php?i=761

    10.05.2017
  • Nem tudom, miért említi a vpxor -t - nem használhatja ezt az utasítást vagy bármilyen egyregiszteres nullázási idiómát a felső piszkos állapot visszaállítására. Nagyon valószínű, hogy a vzeroupper és vzeroall továbbra is gyorsak lesznek a jövőbeni asztali/szerver chipeken, mivel manapság erősen használják a nagy teljesítményű és fordító által generált kódokban. Ez nem olyan, mint a pushad, és nem tudom, hogyan vonta le ezt a következtetést. 10.05.2017
  • @BeeOnRope - Úgy érted, hogy a processzor úgy dönt, hogy a regiszterek piszkosak, amikor megérinti őket (a tényleges értékük nem számít), így a piszkos állapot törlésének egyetlen módja a vzeroupper vagy a vzeroall végrehajtása? Van erről valami hivatalos dokumentum? 10.05.2017
  • @BeeOnRope - Megpróbálom megmérni a vzeroupper valós sebességét, a következő módon - két vmovdqa, majd egy vzeroupper - egy hurokban; majd ugyanaz a ciklus, de vzeroupper nélkül – csak azért, hogy kitaláljuk, vajon a vmovdqa+vzeroupper csak 32 bájtnyi adat másolása gyorsabb-e, mint két 16 bájtos xmm-alapú mov, amelyekhez nincs szükség vzeroupperre. 10.05.2017
  • Igen, különféle tesztek és információk alapján (beleértve az általam linkelt Intel-szálat is) - csak egyetlen magszintű jelző van: piszkos/tiszta a felső állapothoz, és a ymm regs-t használó utasítások beállítják Önt. Tehát az érték nem számít, és nem lehet visszavonni olyan utasításokkal, amelyek véletlenül nullázzák néhány reg magas bitjeit: szükséged van a vzero* srácokra. A Phi nem egy normál CPU, mivel az emberek nem veszik meg egy általános célú CPU helyett – de egy konfigurációban CPUként is működhet. Általában HPC-hez és más speciális feladatokhoz. A háziorvosi kód miatt ne aggódj. 10.05.2017
  • Ha csak 32 bájtot másol, akkor nincs okod aggódni – csak használd a xmm-t: ez csak egy plusz betöltés/tárolás ymm-on keresztül, tehát úgy beszélsz, mint egy ciklus, és az AVX-el és a vzeroupper-al való vacakolás nem megy. kifizetni. Akkor van értelme, ha jelentős területet kell másolni. 10.05.2017
  • A CPUID azt mondja, hogy nem MMX vagy SSE Nem, csak valaki az interneten tévedett. Valószínűleg törölnie kell korábbi megjegyzését, mert az Intel egyik alkalmazottja már kijavította ez a tévhit a KNL-rendszerből származó CPUID-adatokkal kapcsolatban (github.com/xianyi/OpenBLAS/ issues/991#issuecomment-273352067), mielőtt linket tett volna a szálra. A KNL binárisan kompatibilis a Haswell-lel, kivéve a TSX-et. Természetesen nagyon eltérően teljesít, mint a HSW olyan dolgoknál, mint a bájtok keverése... 02.05.2019
  • @PeterCordes - köszönöm, töröltem a korábbi hozzászólást. 02.05.2019
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..