Trådar och Multiprocessorer Föreläsning 6 Trådar och multiprocessorer Hur skriver man program som hanterar många saker samtidigt, t.ex. en web-server som hanterar många samtidiga begäran från olika klienter? Hur kan vi bygga snabbare/kraftfullare datorer? Hur kan vi lösa större beräkningsproblem? Trådar – en programmeringsmodell Trådar i Pthreads, Solaris och Windows Multiprocessorer Behovet av synkronisering Kap: 2.2-2.3, 8.1-8.2 OS Föreläsning 6, Multiprocessorer och trådar 2 Trådar (threads) Trådar - en programmeringsmodell Att tillåta flera processer att exekvera på en dator ger flera fördelar: Tillåter flera samtidiga användare/tasks Kan överlappa beräkning och I/O Återanvänd idén: - många applikationer kan modelleras enklare/bättre om man har ”processer” i processen OS Föreläsning 6, Multiprocessorer och trådar 4 Exempel på program som blir lättare att skriva med trådar Simuleringar Modellerar ofta flera parallella processer Ex: simulering av del av Internet med användardatorer, routrar etc. Serverapplikationer Ex: Webb-server, spelserver Men även många vanliga interaktiva applikationer Ordbehandlare, kalkylprogram... Program med flera fönster, t.ex. grafisk debugger OS Föreläsning 6, Multiprocessorer och trådar 5 Processer och trådar Text (kod) Heap (data) Register Filer Stack Text (kod) Heap (data) Filer Register Register Register Stack Stack Stack tråd Enkeltrådad process (det vi sett hittills) Multitrådad process OS Föreläsning 6, Multiprocessorer och trådar Trådarna delar kod, heap och filer 6 Vad är en tråd? En tråd kan ses som en virtuell CPU eller lättviktsprocess Programräknare Register Stack En process kan ses som en virtuell maskin Adressrymd (minne) En eller flera trådar OS Föreläsning 6, Multiprocessorer och trådar 7 Trådar - fördelar Responstid – hantering av blockerande systemanrop En multitrådad interaktiv/server applikation kan svara på input även om delar (någon/gra trådar) är blockerade eller utför någon tidskrävande operation Dela resurser Flera aktiviteter kan dela kod, data etc. i en process Ekonomi Trådar kräver inte lika mycket egna resurser och är enklare/billigare att skapa och att switcha mellan (ex: Solaris 2 process/tråd: tid för att skapa 30/1, context switch 5/1) Utnyttja datorer med flera processorer Trådar kan (enkelt) utnyttja datorarkitekturer med flera processorer för att exekvera snabbare OS Föreläsning 6, Multiprocessorer och trådar 8 Var implementerar man trådar - i OS-kärnan eller i användarläge (user-space) I användarläge Trådoperationerna är biblioteksrutiner Schemaläggningen görs av run-time system Trådhantering, skapande/dödande omhändertagande av terminerade trådar etc. sköts via biblioteksrutiner och run-time system I kärnan Trådoperationerna är systemanrop Schemaläggningen görs av kärnan trådhantering, skapande/dödande omhändertagande av terminerade trådar etc. sköts via systemanrop och kärnan OS Föreläsning 6, Multiprocessorer och trådar 9 Trådar i kernel-space resp. user-space Run-time system Run-time system Trådtabell User-space OS-kärna User-space Process tabell User threads (användartrådar) OS-kärna Process tabell Tråd tabell Kernel threads OS Föreläsning 6, Multiprocessorer och trådar 10 Om trådar i användarläge Schemaläggning, trådbyte sköts utan systemanrop Färre context switchar ger bättre prestanda Kärnan vet ej om att det finns trådar Kan användas även med gamla operativsystem Schemaläggning i två nivåer Kärnan bestämmer vilken process som skall köra Trådbiblioteket bestämmer vilken tråd inom processen som kör OS Föreläsning 6, Multiprocessorer och trådar 11 Mera om trådar i användarläge Nackdelar med trådar i användarläge Blockeras en tråd så blockeras hela processen dvs. alla trådar i processen Schemaläggning är oftast icke avbrytande (nonpreemptive) Ingen sann parallellitet på multiprocessorer OS Föreläsning 6, Multiprocessorer och trådar 12 Trådar i kärnan Fördelar Kan ha preemptiv schemaläggning Om en tråd blockeras kan en annan tråd i samma process schemaläggas Kärnan kan utnyttja trådar för att själv bli effektivare Kan schemaläggas på olika processorer i en multiprocessor – utnyttja sann parallellitet Nackdelar Trådoperationer är systemanrop - tar längre tid att utföra och kostar mer t.ex i context switch OS Föreläsning 6, Multiprocessorer och trådar 13 Hybrider Hybridformer är vanligast i moderna operativsystem Kärnan tillhandahåller ett visst antal trådar En eller flera användartrådar mappas på en eller flera trådar i kärnan OS Föreläsning 6, Multiprocessorer och trådar 14 Att mappa trådar - användartrådar på kärntrådar Flera användatrådar på en kärntråd ex: Solaris ”green threads” En användartråd på en kärntråd ex: Windows 2000, NT Många användartrådar på en grupp av kärntrådar ex: Solaris, HP-UX, True64 UNIX OS Föreläsning 6, Multiprocessorer och trådar 15 Några praktiska funderingar kring trådar och Systemanrop Trådpooler exec, fork Signaler, kancellering Trådar och systemanrop Exempel: En webserver hämtar en begäran åt gången och utför den Om en begäran medför diskaccess kan servern inte ta emot en ny begäran förr än dess att diskaccessen är klar Slöseri av flera skäl Om man har flera diskar kan de arbeta parallelt Om efterföljande begäran inte behöver diskaccess är det onödigt att de skall vänta Låt servern starta en ny tråd för varje begäran OS Föreläsning 6, Multiprocessorer och trådar 17 Trådar och systemanrop Trådad server Otrådad server while ( True ) { recieve(&request); handle(request); } while ( True ) { recieve(&request); create_thread(&handle,request); } OS Föreläsning 6, Multiprocessorer och trådar 18 Hur många trådar kan man skapa? - trådpooler Oftast finns en övre begränsning Hur gör vi i exemplet med webb-servern? Ha en pool av trådar Den tråd som tar emot en begäran kan göra så här: 1 Om det finns ledig tråd i trådpoolen 2 Ta emot begäran 3 Väck en tråd ur trådpoolen som behandlar begäran 4 Börja om från 1 Den tråd som väcks behandlar sin begäran och lägger sig sedan att sova i trådpoolen OS Föreläsning 6, Multiprocessorer och trådar 19 Trådar som exekverar exec eller fork En tråd exekverar fork Två val: 1. Den nya processen får en tråd 2. Den nya processen blir en exakt kopia av den gamla med lika många trådar En tråd exekverar exec Vanligast är att hela processen, dvs alla trådar, börjar exekvera det nya programmet OS Föreläsning 6, Multiprocessorer och trådar 20 Att döda (kancellera) trådar Inte helt problemfritt... Vad gör man om: Tråden har resurser knutna till sig – lämnas de till - processen? - tar OS:et tillbaka dem? Tråden håller på med något som andra trådar väntar på, eller kan komma att vänta på OS Föreläsning 6, Multiprocessorer och trådar 21 Feltolerans Går det att bygga feltoleranta system genom att utnyttja flera trådar i en process? Frågan att fundera över: Överlever systemet/processen att en tråd får t.ex ett exekveringsfel som segmentation fault eller bus error? Har man behov av att systemet överlever hårda fel kan det vara bättre att bygga på processer som ”isoleras bättre” från varandra OS Föreläsning 6, Multiprocessorer och trådar 22 Att skicka signaler till trådar Om man skickar en signal till en tråd vad gör man då? Levererar signalen bara till den berörda tråden Levererar signalen till varje tråd i processen Levererar signalen till några utvalda trådar i processen Utser en speciell tråd att ta hand om alla signaler (Solaris) OS Föreläsning 6, Multiprocessorer och trådar 23 Exempel på trådimplementationer Pthreads Solaris2 Windows 2000 Java Pthreads POSIX standard som beskriver gränssnitt och beteende (inte hur det ska implementeras) Trådbibliotek och run-time system på användarnivå Allmänt använt på olika UNIX system OS Föreläsning 6, Multiprocessorer och trådar 25 Pthread exempel HELT UTAN FELKONTROLLER... #include <pthread.h> #include <stdio.h> int sum = 0; // shared variable void runner(char *); void runner(char *arg1) { int upper = atoi(arg1); int i; if(upper <= 0) { printf(”talet måste vara > 0\n”); pthread_exit(1); } void main(int argc, char *argv[]) { pthread_t tID; pthread_attr_t attr; pthread_attr_init(&attr); pthread_create(&tID, &attr, runner, argv[1]); pthread_join(tID, NULL); printf(”Summa: %d\n”, sum); } sum = 0; for(i=1; i <= upper; i++) sum += i; pthread_exit(0); } OS Föreläsning 6, Multiprocessorer och trådar 26 Solaris2 Tre nivåer av trådar Tråd på användarnivå: trådId, register, stack och prioritet LWP – light weight process Datastruktur i kärnan med - registeruppsättning för den användartråd som exekverar i LWPn, minne och ”accounting” info Tråd i kärnan Liten datastruktur med liten stack Pekare till ansluten LWP OS Föreläsning 6, Multiprocessorer och trådar 27 Solaris2 forts. Användartrådar Processer (tasks) LWP Kärntrådar Kärnan Processorer OS Föreläsning 6, Multiprocessorer och trådar 28 Kan man tjäna något på att använda trådar? SUN designade om telnet-servern till att använda trådar för att hantera telnetförbindelser På en större server kunde man öka antalet samtidiga uppkopplingar från några hundra till några tusen OS Föreläsning 6, Multiprocessorer och trådar 29 Windows 2000 Ett-till-ett mappning av användartrådar till kärntrådar Flera trådar i en process (tråd schemaläggningsenhet) Bibliotek för ”fibers” – möjlighet att köra flera trådar i en användartråd Datastrukturer Tråd ID Registeruppsättning Användarstack (för exekvering i user-mode) Kärnstack (för exekvering i kernel-mode) Privat dataarea OS Föreläsning 6, Multiprocessorer och trådar 30 JAVA Implementerar trådar i den virtuella maskinen Svårt att klassificera som användar- eller kärntrådar Ett sätt att skapa trådar är genom att Ärva från Thread klassen Överlagra run metoden i Thread klassen OS Föreläsning 6, Multiprocessorer och trådar 31 JAVA exempel HELT UTAN FELKONTROLLER... class Summation extends Thread { public Summation(int n) { upper = n; } public void run() { int sum = 0; if(upper > 0) for(int i = 1; i <= upper; i++) sum += i; } public class ThreadTester { public static void main(String[] args) { Summation thrd = new Summation( Integer.parseInt(args[0])); thrd.start(); } } private int upper; } OS Föreläsning 6, Multiprocessorer och trådar 32 Multiprocessorer Hur bygger vi snabbare datorer? Snabbare datorer Möjliga vägar: Öka klockfrekvensen Minska storleken pga fysiska begränsningar (ljushastigheten) när det gäller att kunna distribuera klockan Problem med värmeproduktion Öka antalet processorer Multiprocessordatorer (hårt kopplade) Datorer i nätverk Flera processorer på ett chip OS Föreläsning 6, Multiprocessorer och trådar 34 Multiprocessorer CPU CPU CPU CPU CPU CPU CPU CPU Minne Minne I/O Buss eller nät I/O Minne Minne OS Föreläsning 6, Multiprocessorer och trådar 35 Multiprocessorer - intressanta designval/parametrar Sammanbindningsnät Buss – begränsar antalet processorer till ~20 Nät: crossbar, switch - antal procesorer upp mot 1000 Fördröjningstid i nätet vid minnessaccess - uniform/icke-uniform, kort/lång Delat minne eller privat Delat minne – allt minne kan accessas direkt av alla processorer – anses ofta enklare att programmera Privat minne – kommunikation med meddelanden OS Föreläsning 6, Multiprocessorer och trådar 36 Cachning i multiprocessorer CPU CPU CPU cache cache cache I/O Minne Minne Cachear minskar lasten på sammanbindningsnätet/bussen Men: - Hur håller man informationen konsistent? - False-sharing problematik OS Föreläsning 6, Multiprocessorer och trådar 37 Schemaläggning på multiprocessorer Frågan är inte bara när utan också var en tråd eller process skall köras För lastbalansering och rättvisa är det bäst att köra en tråd varsomhelst (en ready-kö) För effektivt utnyttjande av processorernas cacheminne/sidhantering/TLB är det bäst att köra en tråd på samma processor som förra gången (en ready-kö för varje processor) OS Föreläsning 6, Multiprocessorer och trådar 38 Varför trådar från samma jobb bör få exekvera samtidigt... Trådar från samma jobb synkroniserar ofta Om schemaläggaren tar ifrån en tråd dess CPU medan den håller ett lås och andra trådar i den processen vill ha låset och systemet använder lås med busy waiting så kommer övriga trådar att få vänta länge OS Föreläsning 6, Multiprocessorer och trådar 39 Schemaläggning forts. Mål: Lastdelning – ingen processor bör vara för lite/mycket lastad Rättvis –processerna ska få sin rättmätiga del av CPU tiden Effektivt utnyttjande av resurser Kommunicerande processer bör få köra samtidigt! Varianter: En gemensam ready-kö – blir lätt flaskhals men bra lastdelning Varje processor har egen ready-kö - lastdelning t.ex. genom att underutnyttjade CPU:er kan fråga andra om de har jobb som de vill bli av med Gängschemaläggning OS Föreläsning 6, Multiprocessorer och trådar 40 Gängschemaläggning (gang scheduling) Alla trådar i en process kör samtidigt på olika CPU:er Alla CPU:er byter process samtidigt Om en tråd blir BLOCKED blir dess CPU idle (ingen annan tråd körs) Kan kombineras med space sharing där olika processer körs på olika grupper av CPUer OS Föreläsning 6, Multiprocessorer och trådar 41 Löst kopplade multiprocessorer/datorer Sammankopplade med nät som har förhållandevis lång fördröjning Det finns/fanns stort intresse för ”GRIDcomputing” – beräkningar på vanliga datorer i nät (Internet) Problemet är att inte få för dålig prestanda pga fördröjningar i nätet Olika applikationer är olika känsliga.... OS Föreläsning 6, Multiprocessorer och trådar 42 En första titt på - ömsesidig uteslutning och synkronisering Behovet av ömsesidig uteslutning Antag en gemensam ready-kö i en multiprocessor Process struct A Process struct B Kod för att hämta en process med prioritet i ready kö new = ready[i]; tmp = new -> next; ready[i] = tmp; Array av ready köer med olika prioriteter OS Föreläsning 6, Multiprocessorer och trådar 44 Ready-kön: Behovet av mutual exclusion Om två processorer samtidigt vill ta ut en ny process ur ready-kön kan följande hända: Den första processorn sätter den lokala variabeln new att peka på process struct A Den andra processorn sätter sin lokala variabel new att peka på samma struct A Bägge processorerna sätter ready[i] att peka på process struct B Bägge processorerna börjar köra samma process! Inte bra ... Resultatet beror av i vilken ordning processorerna exekverar – race-condition OS Föreläsning 6, Multiprocessorer och trådar 45 Ömsesidig uteslutning - mutual exclusion Man använder lås Ett lås kan vara ledigt eller upptaget Man kan låsa och låsa upp lås Om man försöker låsa ett låst lås får man vänta till dess att den som låst det låser upp det Med ett lås för ready-kön gör man så här Lås låset Plocka ut en process Lås upp OS Föreläsning 6, Multiprocessorer och trådar 46 Implementation av lås på multiprocessor lock: test_and_set tmp, (lock_ptr) branch_not_zero tmp, lock unlock: store (lock_ptr), 0 OS Föreläsning 6, Multiprocessorer och trådar 47 Implementation av lås på multiprocessor test_and_set tmp, (lock_ptr) är en maskininstruktion som skriver värdet 1 till minnet på adress lock_ptr läser in gamla värdet till registret tmp låser bussen så att ingen annan processor kommer emellan Denna instruktion kan användas till andra typer av lås också OS Föreläsning 6, Multiprocessorer och trådar 48 Implementation av lås på multiprocessor Om låset är låst hoppar man tillbaka och försöker igen Denna typ av lås kallas spin-locks och gör busy waiting Lämpliga på multiprocessorer, men mycket olämpliga på en-processormaskiner Endast en annan process kan låsa upp låset Man spinner resten av time-slice Andra typer av lås gör processen BLOCKED om låset är upptaget OS Föreläsning 6, Multiprocessorer och trådar 49 Synkronisering Bakom kulisserna i en pipe En pipe implementeras som en buffer i kärnan Finns alltid i huvudminnet Har en viss storlek (några sidor) Om en process vill skriva till en pipe vars buffer är full måste den vänta Om en process vill läsa från en pipe vars buffer är tom måste den vänta Exempel på synkronisering (ofta inbyggt i systemanrop i Unix) OS Föreläsning 6, Multiprocessorer och trådar 51 Bakom kulisserna i en pipe Man måste hålla reda på hur mycket data det finns i bufferten Liknande problem som vid exemplet med ready-kön Semaforer kan användas OS Föreläsning 6, Multiprocessorer och trådar 52 Semaforer En semafor är en räknare som har operationerna upp: öka värdet med ett ner: minska värdet med ett om det ej är noll, vänta i så fall En semaforoperation är odelbar Ingen annan tråd eller process kan komma in emellan Väntande trådar kan läggas i kö OS Föreläsning 6, Multiprocessorer och trådar 53 Bakom kulisserna i en pipe med semaforer Två semaforer används ledig_plats visar mängden ledigt utrymme färdigt_data visar mängden färdigt data Varje operation antas för enkelhets skull skriva eller läsa en byte OS Föreläsning 6, Multiprocessorer och trådar 54 Bakom kulisserna i en pipe med semaforer skriv(data) { ner(ledig_plats) lägg data i buffer uppdatera skrivpekare upp(färdigt_data) } läs() { ner(färdigt_data) ta ut data ur buffer uppdatera läspekare upp(ledig_plats) returnera data } OS Föreläsning 6, Multiprocessorer och trådar 55 Behov av synkronisering och ömsesidig uteslutning Synkronisering och ömsesidig uteslutning behövs också i vanliga en-processors system! Viktigt och klurigt problem att lösa Gör man fel får man ofta fel som är sporadiska och svåra att hitta... OS Föreläsning 6, Multiprocessorer och trådar 56 Summering – vad vi pratat om idag Trådar Multiprocessorer En första titt på synkronisering och ömsesidig uteslutning OS Föreläsning 6, Multiprocessorer och trådar 57 Nästa föreläsning Interprocesskommunikation – IPC Remote Procedure Call – RPC Distribuerade system Distribuerade filsystem OS Föreläsning 6, Multiprocessorer och trådar 58