Hirdetés

Új hozzászólás Aktív témák

  • Dr. Akula

    nagyúr

    válasz Abu85 #98 üzenetére

    Értem hogy a legjobb esetre kell programozni, aztán majd lesz belőle valami az adott hardveren, a kérdés csak az hogy 1. ez mennyire mozgatja az Nvidiát az architektúra váltásra, 2. megfordul-e a FuryX hátránya a 980Ti-hez képest?

  • Ren Hoek

    veterán

    válasz Abu85 #100 üzenetére

    Ez végülis nem akkora egetverő probléma, mivel csak a CPU-nak jelent többletterhelést, nem? Mondjuk egy TIER2 szint esetén ez kb mekkora lehet? Mert ha mondjuk 5-10% az emuláció miatt, az nem egy nagy érvágás...

    Vagy ezt hogyan kell elképzelni, játék közben/játék és DX12 kihasználtság függően dinamikusan változik a többletterhelés, mondjuk egy TIER2-es HW-n - vagy azért kalkulálható előre...?

    [ Szerkesztve ]

  • Abu85

    HÁZIGAZDA

    válasz Dr. Akula #102 üzenetére

    1. Mindenki váltani fog, hogy elérjék a legjobb bekötési szintet. Mindenképpen igazodni kell az API-k alapvető működéséhez.
    2. A Fury előnye az lesz, hogy a GCN-t jobban ismerik a fejlesztők, mivel a teszteket csak ezen a hardveren tudták lefuttatni az elmúlt egy évben. Első körben egyébként nem lesz olyan játék, ami továbbmegy az alapvető DX12-es funkciókon, így async compute/DMA, executeindirect, multi-thread, multiadapter, stb. dolgok lesznek kihasználva. Ezek a legfontosabbak, és a szűkös idő miatt nyilván ezek kapják a fókuszt.

    (#103) Ren Hoek: Senki se mondta, hogy probléma. Azért van szegmentálva az API, hogy le legyen kezelve az egész. Lehetőség szerint úgy, hogy az a fejlesztőknek egyszerű legyen, és eközben minden hardvert elérjenek.

    [ Szerkesztve ]

    Senki sem dől be a hivatalos szóvivőnek, de mindenki hisz egy meg nem nevezett forrásnak.

  • farkas1

    tag

    válasz Raysen623 #90 üzenetére

    #90 Raysen623

    Kívánságod máris teljesült: most vettem egy ismerősnek A10-7870K -t.
    Ebben pont 8 magos az APU :K Rá van írva a dobozára.

  • Raysen623

    addikt

    válasz farkas1 #111 üzenetére

    Véleményt privibe majd írhatnál esetleg róla. Előre is köszi. :C

    A MÁV-nak öt ellensége van: a négy évszak, meg az utasok.

  • farkas1

    tag

    válasz Raysen623 #112 üzenetére

    Ha elindult a gép. Mert még nincs össze rakva. Ja és az APU össz mag 12, rosszul írtam az előbb.
    Sajnos nem az enyém lesz, de ha van közvetett infó, eljuttatom. :K
    Alaplap Asus Crossblade Ranger, memó G.skill DDR3 2x8GB 2400MHz
    Videókártya egy darabig nem lesz benne, úgyhogy direktben az apu fogja futtatni a játékokat. Így lesz róla tapasztalat.

    [ Szerkesztve ]

  • farkas1

    tag

    válasz SylverR #114 üzenetére

    Köszi már javítottam én is :)
    De gondolom az R7 képesség csak dx12-es játékoknál hoz valami előnyt.

    [ Szerkesztve ]

  • Sir Ny

    senior tag

    válasz Abu85 #100 üzenetére

    "Azt nem tudom, hogy a Microsoft megengedi-e a nem validált program szállítását."

    lol?

    -

  • Dr. Akula

    nagyúr

    válasz Abu85 #106 üzenetére

    Arról tudunk valamit hogy a mostani Nvidia karik milyen hátrányban lesznek az AMD-hez képest? Csak úgy nagyságrendben: 10%? fele? tizede? Mennyire lesz sürgős a váltás?

  • SamWarrick

    csendes tag

    Az AMD már megint a saját útját járja...eddig milyen sok jó kisült belőle.

  • SylverR

    senior tag

    válasz SamWarrick #119 üzenetére

    Így van. Rakhatsz a gépedbe 8 giga RAM-ot, vagy akár többet is (64 bites procik)
    Integrált memória vezérlő. Realtime tesszeláció. Most így fejtetőről lesöpörve ennyi jön össze. De össze lehet még szedni többet is.

    Nem!

  • Dr. Akula

    nagyúr

    válasz #32839680 #121 üzenetére

    Mondjuk úgy hogy az x64-el legalizálták az x86 használatát. Mert előtte meg az Intel basztatta őket azért.

  • lenox

    veterán

    válasz #32839680 #123 üzenetére

    Egy processzel többet nem címzel meg (jó esetben) 4GB-nál 32bit alatt.

    En mondjuk csinaltam ilyet, szerintem jo eset volt. Address Windowing Extensions windowson, foglalsz pl. egy 512 MB-os ablakot es 16 db 512 MB-os teruletet, sorban be lehet oket mapelni, igy 8 GB-ot cimezni.

  • Dr. Akula

    nagyúr

    válasz #32839680 #125 üzenetére

    Nem biztos hogy rosszul jártunk volna az x86 örökség elhagyásával. Fájdalmasabb váltás lett volna, de tisztább. Van amit már nem kéne hordozni tovább, de így nincs ami kikényszerítse.

  • hugo chávez

    aktív tag

    válasz Dr. Akula #127 üzenetére

    Mindig előjön ez téma... Nem konkrétan neked címezve, de kérdem, az x86(-64) helyett milyen meglévő ISA-t ajánlanátok általános célú procihoz, olyanhoz, ahová kellenek a szálankénti teljesítményre kigyúrt (latency optimized) magok? Az Itaniumot felejtsük el, mert az EPIC/VLIW uarch, ami pedig egy szuperskalár procihoz képest ebben nem nagyon virít. Szóval, az elterjedtek közül van a szintén "ősöreg" és azóta az x86-hoz hasonlóan reszelegetett ARM, MIPS, SPARC, meg a valamivel fiatalabb POWER (és az abból származó Power PC). Ezekre meg totál felesleges lenne a már szintén "kellően RISC-esedett" x86-ot leváltani szerintem, mert egyik uarch/ISA sem tud már igazi előnyt felmutatni vele szemben.

    Mondjuk ez érdekesnek tűnik... De hogy megérné-e váltani PC-n erre és ezzel bukni a visszamenőleges natív x86 kompatibilitást, hááát...

    [ Szerkesztve ]

    "sajnos ez a beszélgetés olyan alacsony szintre jutott, hogy a továbbiakban már nem méltó hozzám" - by Pikari

  • LordX

    veterán

    válasz hugo chávez #129 üzenetére

    Az x86-al az elavult, nem épp multiprocesszor-barát memóriamodellje a baj. Az Itanium gyönyörűen megcsinálta jól, csak a VLIW ölte meg. A következő, aki ezt megcsinálta, az az ARMv8 (ott az acquire-release helyett SC atomics van, egyesek szerint még jobb).

  • Abu85

    HÁZIGAZDA

    válasz LordX #130 üzenetére

    Igen, az Itanium memóriamodellje tényleg szépen ki volt gyúrva a skálázhatóságra. De az x86-tól sokat nem lehet elvárni. Amikor tervezték, akkor szó sem volt róla, hogy egynél több mag lesz a lapkákban. Ennek következtében nem is merült fel a skálázhatóság mint igény. Akármelyik ISA-val így jártunk volna.

    Az ARM egy kicsit más tészta szerintem. Az új ISA-val nekik tényleg megvan a lehetőségük jól skálázható alapot csinálni a megfelelő CCI interfésszel, de ők nem úgy gondolkodnak, mint az Intel, hogy CPU kell mindenhova, mert nekik eleve nem olyan kritikus hozzáláncolni egy piacot az ARMv8 ISA-hoz. A piac hozzáláncolja magát lényegi alternatíva hiányában. Ez megadja az ARM-nak a lehetőséget, hogy modernebb konstrukciókban is gondolkodjanak, amire már gyúrják is ki a következő Mali-t. :)

    [ Szerkesztve ]

    Senki sem dől be a hivatalos szóvivőnek, de mindenki hisz egy meg nem nevezett forrásnak.

  • LordX

    veterán

    válasz Abu85 #131 üzenetére

    Az ARMv8 is visszamenőlegesen kompatibilis az ARMv1-ig mindennel, ami szintén nem mai darab..

  • hugo chávez

    aktív tag

    válasz LordX #130 üzenetére

    Oké, ez világos. Na de ha szigorúan a PC és mobil vonalat nézzük, ott 8-16 magnál többnek lenne gyakorlati értelme bármilyen memóriamodellel is? Ha valahová nagyon sok szál kell, akkor nem jobb a lebutított apró CPU-származékok helyett egy külön, IGP-szerű tömb, aminek úgy is saját ISA-ja lehet-van, aztán a közös virtuális memórián keresztül meg pofáznak egymással (HSA)? Vagyis nem látom értelmét otthoni felhasználásra olyan CPU-nak, aminél korlátozó lehetne az x86 memóriamodellje azért, mert annyira tele lesz majd apró magokkal (amiknek egy szálon hurka a teljesítményük, ha meg kifejezetten "throughput optimized multicore" tömbként nézzük, arra már most ott van az IGP).

    És egy láma kérdés. Nem lehet az x86 memóriamodelljét "kiegészíteni"? A visszafelé kompatibilitás megtartásával. Akár úgy, hogy a régi modell utána már csak "legacy-ben" lenne elérhető?

    Még valami: [link], [link] Már régóta semmi nem történik ott, de azért úgy évente ránézek nosztalgiából, hátha... Mi a véleményed, mennyire lenne-lehetne jó ez a cucc a jelenlegiekhez (x86, ARM és társai) képest?

    [ Szerkesztve ]

    "sajnos ez a beszélgetés olyan alacsony szintre jutott, hogy a továbbiakban már nem méltó hozzám" - by Pikari

  • LordX

    veterán

    válasz hugo chávez #133 üzenetére

    Nem tudom hogy vagy vele, de PC és mobil vonalon minden chipben max 8 szál (4 x86 mag HT-vel vagy 8 ARM mag) van, mellette egy akkora iGPU-val, ami már több helyet foglal a chipen, mint a 4/8 CPU mag és a cache összesen. Szóval a gyártók szerint sincs (ma) gyakorlati értelme erre a piacra. Szerverekbe meg gyártják a 36 szálas Haswell-EX-et meg a 48/64/192 magos ARM chipeket GPU nélkül

    Lehet kiegészíteni x86 modellt; a TSX utasításkészlet egy ilyen próbálkozás (bár nem abban az irányban, hogy közeledjen az ARM felé), csak azért talán mutatja, hogy egy ilyen kiegészítés mennyire nehéz vállalkozás, hogy az Intel is el is cseszte a TSX első implementációját. Az se segít, hogy az x86-ban gyakorlatilag minden utasítás load/store utasítás, ha az első operandus memóriacím.

    Szerintem ez a TRIPS nem próbálja megoldani ezt a problémát; Ők "csak" azt kutatják, hogy hogyan lehetne ILP növekedést elérni, és szerintük a megoldás az, hogy az OoO helyett implicite kódoljuk bele az utasításkészletbe. Hol is láttam ilyet..

  • P.H.

    senior tag

    válasz LordX #134 üzenetére

    Ezt meg én nem értem: "x86-ban gyakorlatilag minden utasítás load/store utasítás, ha az első operandus memóriacím", nem locked, ha nem XCHG vagy CMPXCHG. Ha el van látva LOCK prefix-szel, akkor lesz atomi, alapesetben nem az az összes többi load-op-store utasítás. Mit korlátoz ez multiprocesszoros környezetben?

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • LordX

    veterán

    válasz P.H. #135 üzenetére

    Nem a read-modify-write, hanem "csak" a read és a write rész külön-külön atomi, ha a felhasznált adat teljesen befér egy cache line-ba (azaz nem lép át 64 byte-os címet) - ez P6 óta van, előtte csak aligned hozzáférés volt atomi. De ez igazából teljesen mindegy, mivel a főmemóriával és a többi processzorral való "kommunikáció" amúgy is cacheline szinten megy. Lásd [1], 8.1 fejezet.

    A probléma az ordering: [1] 8.2.2 Van egy zsák szabály, hogy milyen memóriaművelet mivel lehet felcserélni, de ha megnézed a fejezetet, kb. az jön le, hogy semmit semmivel - kivéve pár esetet - még akkor is, ha egyébként teljesen független memóriacímmel dolgozik az érintett művelet. Ez már egyprocesszoros rendszernél is problémás: Out-of-Order működésnél komoly probléma, ha tilos átrendezned műveleteket. Többprocesszoros rendszerben meg amikor egyik utasítás egy lassú szinkronizációs művelet, a többi utasítás is blokkolva van: egy LOCK INC több, mint 100 órajel, a Haswellben 8 pipeline port van, tehát olyan 800 darab utasítást kéne kiadni, ami nem memóriaművelet, hogy ne álljon üresben a proci. (Hardver szálakról beszélünk, szóval nincs context switch se, hogy "addig futtassunk mást") Van max 4x16 db regisztered, ami elég adatot kell tartalmazzon ehhez a 800 utasításhoz, amíg a LOCK INC fogja a memóriát. Hát, sok sikert.. Egy régi statisztika szerint valós x86 programban az utasítások kb. ötöde memória-operandussal dolgozik. Ja, és nem csak a LOCK INC-et kiadó processzorban történik mindez, hanem mindegyikben, amelyik a memóriához fordulna, miközben valaki LOCKolta a buszt.

    ARM esetében ilyen nincs. Ott minden OoO, ha nincs függőség az utasítások között. A program helyes működése céljából itt ki kell adni a megfelelő acquire-release vagy barrier utasításokat, de ezzel csak a szinkronizációt lassítod, a szál "egyéb" utasításait, a thread_local / stacken levő adatokhoz hozzáférést nem.

    [1]: Intel 64 and IA-32 Architectures Software Developer Manuals, 3.A. kötet

  • hugo chávez

    aktív tag

    válasz LordX #134 üzenetére

    Na ez az! Szerverprociknál és pláne multiprocesszoros környezetben elhiszem, hogy gond lehet az x86 memóriamodellje (elvileg pont emiatt szívás a MIC az Intelnek), de otthoni környezetben már nem annyira. Mert nincs is igény a nagyon sok "valódi procimagra", nem lehetne kihasználni őket észszerűen. És valószínűleg nem is lesz... Amdahl törvénye, "Dark Silicon", stb...

    Nehéz... Ha lenne értelme (szigorúan PC környezetben, ott, ahol valószínű, hogy nem is nyernének túl sokat az általában 4-8 nagy(obb) teljesítményű magnál többet nem igénylő programok miatt) egyáltalán, akkor melyik érné meg jobban? Megpróbálni a nehézségekkel együtt, vagy bevállalni egy totális ISA váltást, annak minden hátrányával (elsősorban a kompatibilitás elvesztése)?

    Nem is konkrétan a memóriamodellre gondoltam, hanem úgy általánosságban összehasonlítva a többi uarch-kal, persze skálázódási szempontból is. Nem nagyon értek ilyen mélységekben ehhez, pont ezért is kérdeztem a véleményed. :) Szóval azt mondod, hogy ez végül is a VLIW-EPIC -hez hasonló, de talán továbbgondolt megközelítés? És a TRIPS-nél valamilyen szinten próbálták hardveresen megoldani azt, amit az Itanium "hiányossága" volt?

    [ Szerkesztve ]

    "sajnos ez a beszélgetés olyan alacsony szintre jutott, hogy a továbbiakban már nem méltó hozzám" - by Pikari

  • P.H.

    senior tag

    válasz LordX #136 üzenetére

    Egyszerűbb lenne, ha egyszerűen beidéznéd a vonatkozó részeket, mert én nem azt látom benne, amit leírtál, hanem ezt:

    8.1.2 Bus Locking

    "Intel 64 and IA-32 processors provide a LOCK# signal that is asserted automatically during certain critical memory operations to lock the system bus or equivalent link. While this output signal is asserted, requests from other processors or bus agents for control of the bus are blocked. Software can specify other occasions when the LOCK semantics are to be followed by prepending the LOCK prefix to an instruction."

    8.1.2.2 Software Controlled Bus Locking

    "To explicitly force the LOCK semantics, software can use the LOCK prefix with the following instructions when they are used to modify a memory location. An invalid-opcode exception (#UD) is generated when the LOCK prefix is used with any other instruction or when no write operation is made to memory (that is, when the destination operand is in a register)."

    "• The bit test and modify instructions (BTS, BTR, and BTC)."
    (bit test&set utasítások)

    "• The exchange instructions (XADD, CMPXCHG, and CMPXCHG8B)."
    (compare&exchange utasítások)

    "• The LOCK prefix is automatically assumed for XCHG instruction."
    (exchange reg<->mem)

    "• The following single-operand arithmetic and logical instructions: INC, DEC, NOT, and NEG."
    (logikai utasítások)

    "• The following two-operand arithmetic and logical instructions: ADD, ADC, SUB, SBB, AND, OR, and XOR."
    (logikai és +/- utasítások)

    Mely eset maradt ki, amikor életbe lép a 8.1.2 fejezet?

    "A locked instruction is guaranteed to lock only the area of memory defined by the destination operand, but may be interpreted by the system as a lock for a larger memory area."
    "Software should access semaphores (shared memory used for signalling between multiple processors) using identical addresses and operand lengths. For example, if one processor accesses a semaphore using a word access, other processors should not access the semaphore using a byte access."

    Alapszabály, hogy aligned cache line-ra nem teszünk egyszerre szinkronizációs változót és adatot. Ezt már ~20 éve tudják a fordítóprogramok. (Persze nyilván meg lehet kerülni; milyen keyword-del tudatod tetszőleges nyelvben, hogy az adott változó módosítása elé tegyen LOCK-ot?
    És milyen eljáráshívással? SetEvent, ResetEvent, WaitForSingleObject, ...)

    A idézetből következik, hogy a fenti utasítások nem zárolják a teljes buszt, hanem csak adott memóriaterületet (ami nagyobb lehet, mint a ténylegesen módosított, praktikusan egy 64 byte-os teljes cache line, hiszen az Intel, az AMD vagy a VIA sem a maga ellensége). Ettől még a többi mag korlátozás nélkül végezheti az utasításvégrehajtást.
    Ha másért nem is egyértelmű ez, az SSE3-ban (Prescott) bevezetett MONITOR és MWAIT utasítások létezése indokolja ilyen belső hardver létezését.

    De megnézhetjük, mennyi is egy-egy locked utasítás végrehajtási ideje: naprakész hardvereken ebből a táblázatból is kinézhető http://agner.org/optimize/instruction_tables.pdf, vagy akár AIDA64-ben az Instruction Latency Dump is megadja LOCK ADD és XCHG mem,reg utasítások futási idejét, amelyen lefuttatjuk.

    K10: XCHG 21 órajel
    Nehalem: XCHG 20 órajel
    Sandy B. XCHG 25 órajel
    Ivy B. XCHG 25 órajel LOCK ADD: 22 órajel
    Haswell: XCHG 21 órajel LOCK ADD: 19 órajel
    Bulldozer: XCHG ~50 órajel LOCK ADD: ~55 órajel
    Piledriver: XCHG ~40 órajel LOCK ADD: ~40 órajel
    Steamroller: XCHG ~38 órajel LOCK ADD: ~39 órajel

    (Nem csak a PCLMULQDQ-ról lehet olvasni általánosan a sajtóanyagokban, hanem a locked műveletek gyorsabb és gyorsabb végrehajtásáról is.)

    Gyakorlatilag magszinten a LOCK-prefixes művelet végrehajtása annyit jelent manapság, hogy amikor találkozik ilyennel a dekóder, akkor addig újabb utasítást nem dekódol, amíg ez végig nem ért a végrehajtási futószalagon és ki nem írta az eredményét egy rendszerszinten látható (=snoopable cache) memóriába (ez általában az L1D, a Bulldozer-család esetében az L2, ezért a nagy időigény).
    A többi mag nyugodtan hajthat végre utasításokat, azokat nem befolyásolja (egy utasítást egy mag hajt végre), mert ha ott is van ugyanerrea memóriaterületre vonatkozó locked módosítás, akkor legfejlebb az nyer...; és nem mondom tovább, tudod.
    Persze ebből össze lehet hozni az adott magon több száz órajeles időidényt, ha a forrásadatot RAM-ból kell beolvasni, de erre - azaz több mag által frekventáltan módosított adatterületek tárolására - vannak kitalálva alapvetően a nagyméretű L3 cache-ek. A TSX teljesen másra való.

    [ Szerkesztve ]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • LordX

    veterán

    válasz P.H. #138 üzenetére

    A 8.1.2 nem tudom hogy jön ide, a 8.1.1-et akartam hivatkozni arra, hogy egy load vagy store akkor atomi, ha befér egy cache line-ba, akkor is, ha nem MOV-ból jön, hanem bármilyen utasítás memory operandussal.

    Ez egy fontos pont: "A locked instruction is guaranteed to lock only the area of memory defined by the destination operand, but may be interpreted by the system as a lock for a larger memory area."

    Agner azt írja, hogy a LOCK utasítások (XCHG-t beleértve) erősen függ a memória sebességétől (ugyanaz a doksi, az első oldal alján a LOCK-ról egy bekezdés), amit bemásoltál, az a "Latency", amit ő úgy definiál, hogy "This is the delay that the instruction generates in a dependency chain. The numbers are minimum values. (.. blabla cache miss, floating point, exceptions ...) The latency listed does not include the memory operand where the operand is listed as register or memory (r/m). Tehát ebben nincs benne a cache és/vagy a memória hozzáférés által generált késleltetés, csak és kizárólag azt jelenti, hogy hány órajel után jöhet egy olyan új utasítás, ami erre az utasításra dependál, attól számítva, hogy a uOP issue megtörtént. Szóval az utasítás végrehajtásának idejének ez csak egy része.

    Hogy hogyan van implementálva a LOCK, azt nem tudom, de egyrészt hardverről hardverre változik, másrészt igazából mindegy; az ordering miatt nem hajthatsz végre egy csomó memóriaműveletet amíg a LOCK be nem fejeződik: 8.2.2, bocs, de most eltekintek az egész fejezet bemásolásától :) Read-re van spekulatív végrehajtás (egyébként e miatt talán annyira nem dramatikus a pipeline stall), de más műveletet nem tud elkezdeni se a proci, és itt jön be az a pipeline bubble, amiről írtam.

    [ Szerkesztve ]

  • P.H.

    senior tag

    válasz LordX #139 üzenetére

    8.1.1 Guaranteed Atomic Operations

    The Intel486 processor (and newer processors since) guarantees that the following basic memory operations will always be carried out atomically:
    • Reading or writing a byte
    • Reading or writing a word aligned on a 16-bit boundary
    • Reading or writing a doubleword aligned on a 32-bit boundary

    The Pentium processor (and newer processors since) guarantees that the following additional memory operations will always be carried out atomically:
    • Reading or writing a quadword aligned on a 64-bit boundary
    • 16-bit accesses to uncached memory locations that fit within a 32-bit data bus

    The P6 family processors (and newer processors since) guarantee that the following additional memory operation will always be carried out atomically:
    • Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line

    Core 2-re elfogyott.

    Accesses to cacheable memory that are split across cache lines and page boundaries are not guaranteed to be atomic by the Intel Core 2 Duo, Intel® Atom™, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6 family, Pentium, and Intel486 processors. The Intel Core 2 Duo, Intel Atom, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, and P6 family processors provide bus control signals that permit external memory subsystems to make split accesses atomic; however, nonaligned data accesses will seriously impact the performance of the processor and should be avoided.

    An x87 instruction or an SSE instructions that accesses data larger than a quadword may be implemented using multiple memory accesses. If such an instruction stores to memory (pl. az FTS(P) tword - azaz 80 bites extended precision tárolás - ilyen) , some of the accesses may complete (writing to memory) while another causes the operation to fault for architectural reasons (e.g. due an page-table entry that is marked “not present”). In this case, the effects of the completed accesses may be visible to software even though the overall instruction caused a fault. If TLB invalidation has been delayed (see Section 4.10.4.4), such page faults may occur even if all accesses are to the same page.

    Erre a fejezetre gondolsz?

    [ Szerkesztve ]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

  • LordX

    veterán

    válasz P.H. #140 üzenetére

    Iiiiigen?

    Mármint mi fogyott el Core 2-re, az unaligned 16/32/64 bites műveletek atomisága? Igen, de én ezt eddig meg se említettem, mert ma már irreleváns.

    De már értem mi hiányzott, nem írtam le, hogy csak 64 bitig igaz a "atomi ha nem lép át cacheline-t" kitétel. Elnézést.

  • P.H.

    senior tag

    válasz LordX #141 üzenetére

    Azért, hogy ne legyen ilyen töredezett a társalgás, legyen egyben az egész.

    8.1.1 bekezdés

    Az első a bekezdés igazából nem közöl érdemleges információt, csak a sorok között. És kizárólag a tárolási műveletekről szól (MOV mem,reg FST(P) mem FIST(P) mem MOVQ mem,mmreg). A 486-os esetén minden kiírt byte bitjei egyszerre jelennek meg a kiírva, továbbá minden 16 bites adaté, ha az páros memóriacímre lett kiírva és minden 32 bites adaté, ha az 4-gyel osztható címre; Pentium 1-nél továbbá minden 64 bites (=MMX, itt jelent meg) adaté, ha az 8-cal osztható címre.

    Ehhez képest a P6 family (Pentium Pro, Pentium 2 és Pentium III) esetén ez lecserélődik arra, hogy bármely 2-, 4- és 8-byte méretű adat bitjei egyszerre jelennek meg kiírva, ha az befér a - az akkor még 32 byte-os - befoglaló cache line-ba, azon belül bárhova (pl. 0x07 címre) írva. Ez a csere a Pentium Pro-val jelent meg, amelyet az Intel az első valóban több CPU-s rendszerekre szánt (aztán a Pentium II sorozatban megjelent a Xeon márkanév), ennyit arról, hogy olyasmivel kell kompatibilisnek lenni, ami még messze nem volt több CPU-s rendszer; technikailag több egymagos CPU és egy többmagos CPU kezelése nem sokban különbözik.
    - azaz ha egy másik mag/CPU ráolvas a változóra, vagy a régi, vagy az új értéket fogja látni, fals értéket nem; és ehhez nem kell külön szinkronizálás
    - magon belül is fontos ez, mert ez teszi lehetővé a store-to-load-forwarding-ot is a magon belül (azaz ha ugyanaz a mag/CPU olvassa vissza a változót), mert a Pentium Pro az Intel első OoO felépítése.

    Ez a szabály azt mondja ki, hogy ha pl. 32 bites single precision lebegőpontos változóban pl. 1.1x2^2 érték van jelenleg és kiírunk oda mondjuk 1.5x2^4 értéket, akkor nem lesz olyan órajel/pillanat, amelyben a változó köztes adatot tartalmazna olyan értelemben, hogy pár bit - monjuk a kitevő byte-ja - már megérkezett, a többi még nem, pl. 1.1x2^4 érték lenne a változóban.
    Persze ettől eltérően ki lehetne írni nem egyben is, csak az még lassabb is lenne. Ez amúgy nem jelentős kitétel, mert a fordítóprogramok már több évtizede gondoskodnak arról, hogy a változók jól legyenek align-olva akár stack-ben vannak, akár globális változók vagy foglalt (malloc) memóriában vannak: pl. egy byte méretű változónak pl. 4 byte-ot foglalnak le, ha utána közvetlenül uint van, vagy az említett extended precision 10 byte-os számnak 16 byte-ot, a rendszer által adott lefoglalt memória pedig NT 3.1 óta 4-byte aligned, Windows Vista óta pedig 32-es címre van igazítva.

    Továbbá megfigyelhető, hogy a szabály nem vonatkozik (a 10 byte-os extended precision mellett) a 128 bites (=SSE) adatokra, pedig az a Pentium III-ban jelent meg. Ennek két praktikus oka van, amit nem itt kell keresni:
    - egyrészt ekkoriban (a Pentium III-ban, a Pentium M-ben és a Pentium 4-ben is) 64 bites végrehajtókon hajtották végre a 128 bites utasításokat, így a tárolásokat is, így garantálni és garantáltatni sem lehetett, hogy a 128 bites adat teljes egésze egyszerre jelenik meg a külvilág számára
    - másrészt az SSE utasítások, legyenek azok load, load-op vagy store jellegűek (load-op-store nincs SSE-ben, sem MMX-ben, sem AVX-ben, legfejlebb non-temporal, de az más téma), per definition megkövetelik, hogy a megadott memóriacím 16-byte aligned legyen. Ellenkező esetben le se futnak, #invalid address (a.k.a. "runtime error 216" vagy "access violation error..." hibát dobnak; erről a programozónak kell gondoskodni (ez nem nehéz, mert a virtuális és a lefordított fizikai memóriacím 4 KB-os lapnál a 12. bittól felfele különbözik csak, tehát programíráskor látható az igazítás).

    Az SSE utasítások a Core 2-ben kaptak natív 128 bites végrehajtókat és hamarosan (vagy a Westmere-ben, vagy a Nehalem-ben; AMD-nél a K10-ben) eltörölték a 16 byte-aligned memóriacím követelményt, a 128 bites adatokra vonatkozó kitétel mégse jelent meg a szabályban ("elfogyott"). Ahogy a 256 bites AVX sem. Pedig kaphatott volna. Hogy bonyolultabb legyen a kép. Vagy elavultabb?

    A tárolás időigénye a fentiek miatt attól függ, hogy hol van az a cache line, amire tárolunk, mivel a tárolás maga csakis az L1-be történhet (hacsak nem non-temporal, akkor meg nem függ attól, hogy van), ezért az L1-be kell hozni az adott cache line-t. Ha legrosszabb esetben RAM-ban van és nincs meg egyetlen közelebbi cache szinten se, akkor sok-sok órajelbe kerülhet. Szerencsére Intel-nél Core2 óta, AMD-nél K10 óta out-of-order a tárolás is (gondolom a store queue, teljes nevén Store Queue for L1-miss Stores szólíthatjuk, mint CPU építőelem ismerős) és mérete szokás szerint nő generációról generációra, közben az utasításvégrehajtás kedvére folytatóthat. (persze ha betelik a retirement window, azaz a ROB közben, akkor van baj, dehát azért optimalizálunk, hogy az L1-hit 95% felett legyen, bár a nagy részben megoldják a hardware prefetch-erek.

    A második bekezdés már igenis hordoz lényegi információt. A fordítók készítői számára.

    Mégpedig azt, hogy a tárolás nem fér fele 1 cache line-ba, akkor a fenti nem igaz, ez az eset két db tárolási műveletként van implementálva, fele ide, fele oda, a rendszer semmilyen törekvést nem tesz arra, hogy kívülről egyszerre lehessen látni a teljes adatot. Emiatt a programozónak kell gondoskodnia arról, hogy ha az adott adatra ráolvas másik mag/CPU, egy - mostmár 64 byte-os - cache-egységen belül legyen, de mint említettem, a fordítóprogramok ezt elvégzik. Persze szorgos munkával meg lehet ezt kerülni, szorosan típusos nyelvekben mondjuk nem, C-ben hosszadalmas és jól látható pointer+typecasting-gel, vagy ASM-ben pl. megnöveled a stack pointer-t eggyel, de ugye ez mind proaktív dolog.

    Amúgy a Bulldozer esetében az AMD valószínűleg pont ezt tolta túl és lett 20+ órajel egy 256 bites store, mert a 256 bites AVX tárolásokra egy modulban egyetlen 128 bites FSTORE tároló végrehajtási egysége van a megosztott FPU-ban, viszont a write-through L1D cache miatt az L2-be kell átvinni az adatot és a Write Coleascing Cache-ben megpróbálták egyesíteni a két felet. Aztán a Kaveri-vel vissza is léptek ettől, mert a szabály ezt nem írja elő; más kérdés, hogy az Intel az AVX-et tudó processzorait eleve 256 bites tárolóporttal szerelte fel.

    8.1.2 bekezdés

    Tehát a fentiek a store illetve a másik mag/CPU által kiadott load vagy load-op kapcsolatát írják le. Van még egy eset: van egy változó, legyen VAR, ami kezdetben 0; a feladatot elosztottuk két szálra, amelyek növelik ennek értékét (pl. számolnak valamit). Ha mindkét szál lefuttatja az ADD [VAR],1 utasítást mint load-op-store műveletet, akkor nem garantált, hogy nem fog előfordulni, hogy - mivel az újabb CPU belül több mikroműveletre bontotta az utasítást, régi in-order CPU pedig a futószalag elején beolvas, közepén módosít, a végén ér), hogy beolvasva az érték 0, növelve 1, kiírva 1 lesz: azaz 2 helyett 1 lesz az eredmény.

    Ezen az utasítások elé lehet kitenni a LOCK prefix-et, azaz LOCK ADD [VAR],1 lesz írva mindkét szál kódjába.
    Csak ezen load-op-store utasítások elé, store vagy load-op elé nem lehet, különben jön az #UD, és csak a felsoroltak elé, tehát nincs shift vagy ROR forgatás.

    A rendszer garantálja, hogy ha azonos órajelben indul el mindkét utasítás, akkor is lesz egy sorrend, amelyben az egyik beolvassa-megnöveli-kiírja (az első snoopable szintre, L1 vagy Bulldozernél és Pentium 4-nél L2) az 1 értéket, majd ezt kapja meg a másik szál utasítása, növeli és kiírja a 2-t.
    Amíg le nem fut az ilyen LOCK prefix-szel megjelölt utasítás, addig az adott mag/CPU nem dekódol több utasítást; ez az első magnál lehet gond, mert lehet, hogy neki kell (ha kell) beolvasni RAM-ból az adatot (load-op-store, tehát kell a forrásadat is), eredményét az L1-ből vagy L2-ből közvetlenül megkapja a másik mag/CPU. De hogy ne kelljen RAM-olvasás, van L3; vagy ha Broadwell-t veszel, akkor méretes L4 is.

    Az egyetlen utasítás, ami elé nem kell kiírni a LOCK-ot, az XCHG mem,reg, mert - ahogy a fejezet is említi -, a CPU automatikusan odagondolja.

    Ezek által lehet kezelni a szinkronizációs változókat.

    Meglehetősen nehéz kimérni egy memóriaoperandusú utasítás végrehajtását (meg amúgy életszerűtlen), ha az L1-hozzáférés időigényét nem számolod hozzá... De ha sűrűn módosítod a változót, megtalálod az L2-ban vagy az L3-ban (adj a kiírt órajelhez ~15 vagy ~25 órajelet Intel-nél); ha meg nem, akkor 600 órajel se tétel.

    8.2.2 bekezdés

    Ennek felelnek meg teljes egészében a leírtak. Hogy konkretizáljam:

    - az LFENCE, MFENCE, SFENCE, MOVNTxx non-temporal utasítások, külön faj (a lényegük, hogy semmilyen konzisztenciát nem biztosítanak, a tárolt adat semelyik cache-ben nem jelenik meg, egy átmeneti pufferből azonnal a RAM-ba kerül, jelentősen gyorsabb így nagy mennyiségű adat kezelése, mintha cache-be tennék az eredményt, és a cache tartalma is megőrizhető. Az MOVNT-csoport ír, a FENCE-csoport puffert ürít).
    - a CLFLUSH a Cache Line Flush to RAM, pl. ha laptáblát módosítasz (pár bitenként egyszerre, mint hozzáférési jogok, címrész) és végül globálisan láthatóvá akarod tenni.
    - az I/O műveletek (IN és OUT egy megadott portra) ugyanúgy viselkednek, mint a LOCKED prefix-es utasítások, addig nem dekódol a CPU, amíg ez véget nem ért.

    "Reads may be reordered with older writes to different locations but not with older writes to the same location.[I/]"
    Ha ez nem így van bármely CPU-t, a teljes integritást veszélyezteti.

    "Writes are not reordered with older reads."
    Szintúgy.

    "The only enhancements in the Pentium 4, Intel Xeon, and P6 family processors are "
    "• Added support for speculative reads, while still adhering to the ordering principles above."
    Ez tisztán hardware-es. Nagyrészt kiüti "Reads are not reordered with other reads." kitételt, látszólagos megfelelőséget biztosít neki; továbbá az előző pontot is spekulatívvá teszi, nem kell tudni előre, hogy a korábbi tárolás milyen címre történik; ha kiderül később, hogy azonosra, újraindítja a pipeline-t, mint egy sima branch misprediction-nál. Memory Disambiguation a neve.

    "• Store-buffer forwarding, when a read passes a write to the same memory location."
    Ezt említettem fejlebb, a load vagy load-op utasítás a store queue-ből veszi a kiírt adatot, nem az L1-ből.

    A képen látható bal "Writes are in order with respect to individual processes." és a jobb "Writes from all processors are not guaranteed to occur in a particular order." pedig magáért beszél.

    [ Szerkesztve ]

    Arguing on the Internet is like running in the Special Olympics. Even if you win, you are still ... ˙˙˙ Real Eyes Realize Real Lies ˙˙˙

Új hozzászólás Aktív témák