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