Föreläsning 15: Parallella subrutiner Parallellitet Processer och trådar Semaforer, monitorer och synkroniseringsmeddelanden Parallellitet Ofta är det nödvändigt eller önskvärt att programdelar exekveras parallellt (jämlöpande, eng. concurrently). Det kan handla om fysisk parallellitet två eller fler processorer används logisk parallellitet konceptuell parallellitet som fysiskt kan vara sekventiell ("interleaving") Nivåer på vilka parallellitet kan förekomma är instruktionsnivå maskininstruktioner exekveras parallellt satsnivå enstaka programsatser exekveras parallellt underprogramnivå underprogram exekveras parallellt programnivå flera program exekveras parallellt Varför parallella underprogram? De är "naturliga" Ofta avbildar program den parallella realiteten (t.ex. reaktiva system, simuleringsprogram, osv.) De ger bättre möjligheter att utnyttja datorn Om datorn har flera processorer utnyttjas de på det viset som programmet tjänar mest på De behövs i många interaktiva system Om något komplext beräknas behöver inte användaren vänta utan kan jobba på eller eventuellt ingripa Lämpliga begrepp i språket behövs 1
Processer och trådar Exekveringen av ett parallellt program består av flera kontrollflöden som kallas trådar (eng. threads). En process (eng. ofta "task"=uppgift) är en enhet som kan exekveras parallellt med andra och som kontrollerar en tråd. Synkronisering behövs för att bearbeta gemensamma data synkronisering garanterar att sats S av tråd T exekveras före eller efter sats S av tråd T tävlande synkronisering (eng. competition synchronization) förekommer om en resurs (t.ex. skrivare) inte kan delas (mutual exclusion); turordningen är oviktig samarbetande synkronisering (eng. cooperation synchronization) förekommer vid gemensamma mål; turordningen är viktig (ex: producer-consumer) Processer En scheduler fördelar processer på processorer Heavyweight eller lightweight processer Möjliga tillstånd: Nyskapad Ready Running Blockerad Död Möjliga problem Deadlock Utsvältning (=> Fair scheduling) Icke-determinism Hastighetsberoende (realtid) Semaforer En semafor (Dijkstra 1965) är en datastruktur med två atomära operationer wait och release. Ofta omger de kod som ska synkroniseras. En semafor har en räknare (kapacitet) 0 och en väntekö (initialt tom) för blockerade processer Om en process P exekverar wait(s) och semaforens kapacitet är > 0 minskas den med 1 annars ställs P i semaforens väntekö Om en process P exekverar release(s) och väntekön är tom ökas dess kapacitet med 1 annars får första processen i väntekön fortsätta (och givetvis tas den bort från kön) 2
Semaforer Semaforoperationerna måste vara odelbara! Programmerarens ansvar att semaforen kontrollerar resursen som avsett. Lätt att göra fel! Initialvärde =1 => mutual exclusion (binär semafor) Exempel: buffert med plats för ett värde nonempty := 0; nonfull:= 1 producer: consumer: wait(nonfull) wait (nonempty) lägg in data hämta data release(nonempty) release (nonfull) Semaforer Om flera semaforer ; ordningen viktig! nonempty := 0; free:= N; access:=1 producer: wait(free) wait(access) lägg in data release(access) release(nonempty) consumer: wait (nonempty) wait(access) hämta data release (access) release (free) Omkastad ordning mellan t ex wait(access) och wait(nonempty) kan leda till deadlock Monitorer En monitor inkapslar datastrukturer och operationerna som ger access till dem. (ADT!) Endast en process i taget får tillträde till monitorn. För att möjliggöra samarbetande synkronisering finns det en datatyp queue vars operationer delay och continue endast kan exekveras i en monitor. Om delay(q) exekveras blockerar processen. Den ställs i kön q och andra processer får tillträde till monitoren. Om continue(q) exekveras släpper processen monitorn och första processen som väntar i q får fortsätta (om en sådan finns). 3
Synkroniseringsmeddelanden I Ada kan processer skicka och ta emot synkroniseringsmeddelanden. Om både sändaren och mottagaren är beredda sker ett rendezvous, annars väntar den ena. accept xyz(<parametrar>) <body> betyder "vänta tills någon process P skickar meddelandet xyz och exekvera <body> sedan, medan P är blockerad" Rendezvous Time Lines Synkroniseringsmeddelanden Icke deterministiskt urval sker med select-strukturen: select when <villkor> => accept abc( ) or when <villkor> => accept xyz( ) end select En task deklarerar anropbara entry points som den accepterar anrop till. Andra tasks kan anropa dem. (Se exempel, avsnitt 13.5.5) 4
Jämförelse Semaforer är primitiva och flexibla, känsliga för fel, problemet är att olika programdelar måste samarbeta på mycket låg nivå. Monitorer liknar ADT:er och har liknande fördelar men samarbetande synkronisering förblir komplicerad. Synkroniseringsmeddelanden är enklare och flexiblare än monitorer, men minst lika strukturerade. De passar dessutom bra till distribuerade system. Parallellitet på satsnivå High Performance Fortran Distribuerar data på flera processorer som exekverar samma kod, SIMD Funktionella språk, ingen inbyggd sekvensialitet, olika typer av parallellism möjliga. Inga sidoeffekter, endast databeroende styr exekveringsordningen. Deluttryck kan evalueras i godtycklig ordning, även parallellt (Church-Rosser!) Inga nya språkonstruktioner nödvändiga (i princip), implicit parallellism Undantagshantering Ett program som inte klarar av händelser som avviker från det normalt förväntade (exceptions ) är inte robust. Önskvärt att i programmet - kunna specificera vad som ska göras när vissa undantag uppträder (hantera u.) - kunna skilja detta från huvudalgoritmen 5
Centrala frågor: Undantagshantering (forts) Hur deklararar man ett undantag? Vilken räckvidd har det? Kan ett undantag ha parametrar? Hur aktiveras ett undantag? Hur binds ett aktiverat undantag till en hanterare? Hur definierar vi de enheter som ska hantera ett aktiverat undantag? Var fortsätter exekveringen efter hanteringsrutinens slut? Ett exempel: exceptions i Ada Inbyggda + användardefinierade undantag Hanterare kan knytas till ett block / underprogram / paket / task Undantag kan ej ha parametrar När ett undantag aktiveras avslutas enheten, kontrollen går till hanteraren Om ingen hanterare finns propageras undantaget till omslutande paket / anropande underprogram. Ada, exempel procedure P is BAD_FORMAT: exception; procedure Q is begin if S/= then raise BAD_FORMAT; end if end Q procedure R is begin Q; exception when BAD_FORMAT=>handler body 1 end R begin R; Q; exception when BAD_FORMAT=>handler body 2 end P; 6