Manuál pro začátečníky Protokol MESI Manuál pro začátečníky rev 1.1 Štěpán Rezek, 2007
Co to je? Protokol MESI (někdy nazýván Illinois protocol) je protokol široce používaný pro zajištění paměťové koherence. Poprvé se objevil u procesorů Intel Pentium.
Stavy MESI Tzn. v jakém stavu mohou být kopie proměnných v lokálním bloku M – modified E – exclusive S – shared I – invalid
Stav M Blok cache je přítomen pouze v lokální cache Kopie byla změněna, tzn. hodnota je jiná než hodnota v hlavní paměti Cache musí tento blok zapsat do hlavní paměti dříve, než kterákoliv jiná cache přečte (v tuto chvíli již neplatnou) hodnotu z hlavní paměti
Stav E Blok je přítomen pouze v lokální cache, ale je clean (čistý) – jeho hodnota je stejná, jako hodnota v hlavní paměti
Stav S Blok je platný a může být sdílen jinou cache
Stav I Blok v cache je neplatný
Cache může vrátit hodnotu, když je blok ve stavu M, E nebo S. Pokud je ve stavu I, musí nejdříve získat platnou hodnotu proměnné, aby uspokojila čtení. Poté se může přepnout do stavu S nebo E.
Takže to shrňme: Stav hodnoty v cache: M Modified E Exclusive S Shared I Invalid Je hodnota v cache platná? ANO NE Hodnota v hlavní paměti je… …zastaralá …platná — Existují nějaké kopie v cache ostatních procesorů? Možná možná Zapsání (write) do takového bloku … …nejde na sběrnici …jde na sběrnici a aktualizuje cache …jde přímo na sběrnici, změna hodnoty jen v cache
Transakce (události) na sběrnici BusRd: Po lokálním Read miss, použit S/S – signalizuje, jestli existují sdílené kopie BusRdX: po lokálním Write miss, žádost o nový blok + zneplatnění BusUpgr: po lokálním Write hit nad blokem se stavem S (zneplatnění) Odpověď na čtení (BusRd nebo BusRdX): MemSup: hlavní paměť dodává požadovaný blok do cache CacheFlush: zdrojem dat je cache, kde je blok ve stavu. Data jsou vypláchnuta na sběrnici a uložena do hl. paměti i předána žádající cache.
S/S signál Pokud by neexistoval, máme protokol MSI -> neodlišitelnost stavu E od S => Kontrolery všech cache provádí snooping (číhají) na BusRd Implementováno jako kus drátu, realizující log. funkci OR -> není to sběrnice
na sběrnici půjde operace na sběrnici půjde operace BusRd, Jak spolu souvisí stavy bloků a operace na sběrnici? PrWr/BusRdX PrWr/— BusRd/Flush PrRd/ BusRdX/Flush PrWr/- PrRd/— E M I S PrRd BusRd(S) BusRdX/MemSup BusRd/ MemSup PrWr/BusUpgr BusRd (S) BusUpgr/- procesor zapisuje + na sběrnici půjde operace BusRdX Přechod vyvolaný právě aktivním procesorem Přechod vyvolaný Okolním světem procesor čte + na sběrnici půjde operace BusRd, na S/ S je hodnota 0 (S)
hodnoty z hlavní paměti) Systém používající MESI: Stav, v němž je blok cache Blok (kopie hodnoty z hlavní paměti) Procesor n P0 P1 Pn Hlavní paměť S/S - sdílený signál, log. OR Nutný kvůli stavu E Cache (skrytá paměť) Datová sběrnice
Na začátku jsou všechny bloky ve stavu Invalid P0 P1 P2 E I 5 ? I ? I ? BusRd 5 Procesor 0 chce číst hodnotu > Čtení z hlavní paměti (MemSup), stav Exclusive Read Miss, ostatní procesory neoznamují po S/S, že mají kopii (stav sběrnice = S, tedy log. 0)
Procesor 2 chce číst hodnotu 5 I ? S I 5 ? BusRd 5 Procesor 2 chce číst hodnotu Čímž se u obou nastaví stav Shared, a P2 načte hodnotu z hlavní paměti (MemSup) Operaci BusRd zachytí kontroler cache 0… …a nastaví S=1 na S/S
Procesor 2 chce zapsat hodnotu 9… PrWr(9) S I 5 I ? M S 9 5 BusUpgr(x) 5 Procesor 2 chce zapsat hodnotu 9… … bingo! Už mám platnou hodnotu v cache. Kontroler nejprve musí zneplatnit kopie v ostatních cache… …a potom teprve uvede blok do stavu M
Procesor 0 chce číst hodnotu. Problém – blok je Invalid. 5 9 I ? M S 9 CacheFlush(9) BusRd 9 5 Procesor 0 chce číst hodnotu. Problém – blok je Invalid. -> Na sběrnici se vyšle operace BusRd Ten je zachycen kontrolerem cache 2 -> vyšle S=1 na S/S … a zároveň CacheFlush, s hodnotou 9
Procesor 1 chce zapsat hodnotu, která není v cache PrWr(11) S I 9 M I E 11 ? 9 S I 9 BusRdX BusRdX 9 Procesor 1 chce zapsat hodnotu, která není v cache Kontroler cache vyšle operaci BusRdX, kterou zneplatní ostatní kopie bloku a vezme hodnotu z hlavní paměti Tato hodnota je vrácena zpátky – stav Exclusive a následně změněna procesorem na zapsanou –stav Modified
Poznámka Existuje ještě vylepšení protokolu MESI, nazvané MOESI Ten je využíván např. u procesorů AMD64 Owned -> blok v tomto stavu drží nejčerstvější správnou kopii hodnoty z hlavní paměti. Narozdíl od stavu Shared, hodnota v hlavní paměti může být neplatná. Pouze jeden procesor může mít blok ve stavu O, všechny ostatní musí mít bloky ve stavu S.
Nastal čas na přestávku a přípravu čaje…
Transakce na sběrnici, ještě jednou BusRd: Po lokálním Read miss, použit S/S – signalizuje, jestli existují sdílené kopie BusRdX: po lokálním Write miss, žádost o nový blok + zneplatnění BusUpgr: po lokálním Write hit nad blokem se stavem S (zneplatnění) Reakce na čtení (BusRd nebo BusRdX): MemSup: hlavní paměť dodává požadovaný blok do cache CacheFlush: zdrojem dat je cache, kde je blok ve stavu. Data jsou vypláchnuta na sběrnici a uložena do hl. paměti i předána žádající cache.
Kritické sekce & MESI Implementuje se pomocí sdílené proměnné Lock - zámek Postup: Zamkni zámek Něco vykonej Odemkni zámek Toto musí být atomické
Několik atomických metod Test & Set Swap Fetch & Increment Compare & Swap
Musí celá proběhnout atomicky, tzn. v průběhu Read,Modify,Write Test & Set Musí celá proběhnout atomicky, tzn. v průběhu Read,Modify,Write nesmí ostatní procesy/ory přistoupit do místa v paměti, které je modifikováno Definice Pseudo C++: int TestAndSet(boolean &zamek) { boolean predchoziStav = zamek; zamek = true; return predchoziStav; } Pseudo ASM: Load r, zamek Store zamek, #1 Ret Použití int zamek = false; void KritickaSekce() { while(TestAndSet(zamek) == true); // kod kriticke sekce zamek = false; } Z: TestAndSet r, zamek Bnz r,Z ; kod kriticke sekce Ret Opuštění kritické sekce = nastavení zámku na false (0)
Test & Set + MESI: Load r, zámek Store zámek, #1 Bnz r, Z Bnz r, Z ;projde Load r, zámek Store zámek, #1 Bnz r, Z Load r, zámek Store zámek, #1 Bnz r, Z Test & Set + MESI: P0 P1 P2 P3 1 zámek= zámek= zámek= zámek= I ? I ? I M E 1 ? I ? BusRd zámek= Procesor 2 chce vstoupit do kritické sekce Žádná jiná cache nesdílí zámek -> na sběrnici zůstává S=0 Procesor nyní zamyká zámek... C2 neposílá BusUpgr, protože je v M… … a nyní P2 může nerušeně vykonávat kód v kritické sekci.
Store zámek, #0 BusUpgr Nakonec P2 kritickou sekci opustí…. zámek= zámek= zámek= zámek= I ? I ? M 1 I ? BusUpgr zámek= Nakonec P2 kritickou sekci opustí…. a cache pošle BusUpgr.
Load r, zámek Store zámek, #1 Bnz r, Z CacheFlush(0) BusUpgr BusRd zámek= zámek= zámek= zámek= M S I 1 ? I ? S M I I ? CacheFlush(0) BusUpgr BusRd zámek= Nyní chce P0 uzamknout zámek Procesor P0 chce vstoupit do kritické sekce a Cache0 pošle BusRd. => Změna stavu Cache0 na M a poslání BusUpgr To zachytí Cache2 a nastaví S=1 , načež pošle CacheFlush(0) .
Load r, zámek Store zámek, #1 Bnz r, Z BusUpgr BusRd 1 I 1 M S I 1 ? I I ? CacheFlush(1) BusUpgr BusRd zámek= 1 Teď chce P1 uzamknout zámek. Cache0 zjistí, že někdo chce číst zámek, a tak pošle na S/S jedničku a zároveň CacheFlush(1) na sběrnici. Test ovšem neprojde, jelikož r=1 => zpátky na Začátek Procesor 1 tedy načte hodnotu r=1. P1 poté uloží do cache jedničku a pošle BusUpgr.
Load r, zámek Store zámek, #1 Bnz r, Z 1 P0 P1 P2 P3 zámek= zámek= zámek= zámek= I 1 S M I 1 I M S I 1 ? 1 zámek= Procesor 3 chce taky vstoupit do kritické sekce. Na sběrnici se objeví BusRead od Cache3, následně Cache1 Nastaví S/S na 1 a pošle CacheFlush. Výsledná hodnota r=1. Nakonec P3 nastaví svůj blok na jedničku a dopadne stejně, jako P1 v minulém slidu -> znovu na začátek. P0 je zabarikádován v kritické sekci
Co dál? Protokol MESI se také dá použít, mimo jiné, i s jinými technikami přístupu do kritických sekcí, např. LLSC (Load Linked & Store Conditional), nicméně princip je v základu stejný.
To je vše, mnoho štěstí při zkoušce! I když, no, pro jistotu, ještě chvilku zůstaňte….
Příklad V systému je 5 procesorů v SMP na sběrnici s protokolem MESI. Určete, které transakce a kolikrát se objeví na sběrnici, když: každý procesor se snaží 1x dostat do CS každý zbývající procesor se jednou zkusí dostat do CS, která je zamčená. na začátku mají všechny bloky stav I
Ugh… P0 P1 P2 P3 P4 I ? I ? I ? I ? I ? zámek= zámek= zámek= zámek= zámek=
Simulace, jak by to mohlo vypadat: Read Write P0 Read Write P1 Read Write P2 Read Write P3 Read Write P4 zámek= zámek= zámek= zámek= zámek= E M S I I 1 ? M S I I S ? 1 M S I ? 1 I ? I ? 1 P0 se zamkne v CS, ostatní se budou neúspěšně pokoušet o totéž zámek= Zbytek už je asi zřejmý… BusRd BusRdX BusUpgr P0 P1 P2 P3 P4
Tak to už je skutečně vše
Odkazy https://www.cs.tcd.ie/Jeremy.Jones/vivio/caches/MESI.htm Vynikající simulátor protokolu MESI (WIN only) http://cs.felk.cvut.cz/~brabect1/X36APS/pdf/aps_cv12.pdf WTWNA - Manuál pro začátečníky http://service.felk.cvut.cz/courses/X36APS/ Manuál pro pokročilé
Formality Dílo uvolňuji pod licencí Creative Commons Attribution 2.5 License Zříkám se jakékoli odpovědnosti za škody způsobené tímto textem (třeba 4 u zkoušky… ) A za správnost tohoto textu (chyby ale samozřejmě rád opravím) Drobné nepřesnosti upravil Ing. Miloš Bečvář