2. Informatik im Fokus
Rauber, T.; Rünger, G.
Multicore: Parallele
Programmierung. 2008
El Moussaoui, H.; Zeppenfeld, K.
AJAX. 2008
Behrendt, J.; Zeppenfeld, K.
Web 2.0. 2008
Bode, A.; Karl, W.
Multicore-Architekturen. 2008
3. Thomas Rauber · Gudula Rünger
Multicore:
Parallele Programmierung
123
5. Vorwort
Nach vielen Jahren stetigen technologischen Fortschritts in
der Mikroprozessorentwicklung stellt die Multicore-Techno-
logie die neueste Entwickungsstufe dar. F¨ hrende Hard-
u
warehersteller wie Intel, AMD, Sun oder IBM liefern seit
2005 Mikroprozessoren mit mehreren unabh¨ngigen Pro-
a
zessorkernen auf einem einzelnen Prozessorchip. Im Jahr
2007 verwendet ein typischer Desktop-PC je nach Ausstat-
tung einen Dualcore- oder Quadcore-Prozessor mit zwei
bzw. vier Prozessorkernen. Die Ank¨ ndigungen der Prozes-
u
sorhersteller zeigen, dass dies erst der Anfang einer l¨nger
a
andauernden Entwicklung ist. Eine Studie von Intel prog-
nostiziert, dass im Jahr 2015 ein typischer Prozessorchip
aus Dutzenden bis Hunderten von Prozessorkernen be-
steht, die zum Teil spezialisierte Aufgaben wie Verschl¨ sse-
u
lung, Grafikdarstellung oder Netzwerkmanagement wahr-
nehmen. Ein Großteil der Prozessorkerne steht aber f¨ r u
Anwendungsprogramme zur Verf¨ gung und kann z.B. f¨ r
u u
B¨ ro- oder Unterhaltungssoftware genutzt werden.
u
Die von der Hardwareindustrie vorgegebene Entwick-
lung hin zu Multicore-Prozessoren bietet f¨ r die Software-
u
6. VI Vorwort
entwickler also neue M¨glichkeiten, die in der Bereitstel-
o
lung zus¨tzlicher Funktionalit¨ten der angebotenen Soft-
a a
ware liegen, die parallel zu den bisherigen Funktionalit¨ten
a
ausgef¨ hrt werden k¨nnen, ohne dass dies beim Nutzer zu
u o
Wartezeiten f¨ hrt. Diese Entwicklung stellt aber auch einen
u
Paradigmenwechsel in der Softwareentwicklung dar, weg
von der herk¨mmlichen sequentiellen Programmierung hin
o
zur parallelen oder Multithreading-Programmierung. Bei-
de Programmierformen sind nicht neu. Der Paradigmen-
wechsel besteht eher darin, dass diese Programmiertechni-
ken bisher nur in speziellen Bereichen eingesetzt wurden,
nun aber durch die Einf¨ hrung von Multicore-Prozessoren
u
in alle Bereiche der Softwareentwicklung getragen werden
und so f¨ r viele Softwareentwickler eine neue Herausforde-
u
rung entsteht.
Das Ziel dieses Buches ist es, dem Leser einen ers-
ten Einblick in die f¨ r Multicore-Prozessoren geeigneten
u
parallelen Programmiertechniken und -systeme zu geben.
Programmierumgebungen wie Pthreads, Java-Threads und
OpenMP werden vorgestellt. Die Darstellung geht dabei
davon aus, dass der Leser mit Standardtechniken der Pro-
grammierung vertraut ist. Das Buch enth¨lt zahlreiche Hin-
a
weise auf weiterf¨ hrende Literatur sowie neuere Entwick-
u
lungen wie etwa neue Programmiersprachen. F¨ r Hilfe bei
u
der Erstellung des Buches und Korrekturen danken wir J¨rg o
D¨ mmler, Monika Glaser, Marco H¨bbel, Raphael Kunis
u o
und Michael Schwind. Dem Springer-Verlag danken wir f¨ r u
die gute Zusammenarbeit.
Bayreuth, Chemnitz, Thomas Rauber
August 2007 Gudula R¨ nger
u
9. 1
Kurzuberblick
¨
Multicore-Prozessoren
Die Entwicklung der Mikroprozessoren hat in den letzten
Jahrzehnten durch verschiedene technologische Innovatio-
nen immer leistungsst¨rkere Prozessoren hervorgebracht.
a
Multicore-Prozessoren stellen einen weiteren Meilenstein in
der Entwicklung dar.
1.1 Entwicklung der Mikroprozessoren
Prozessorchips sind intern aus Transistoren aufgebaut, de-
ren Anzahl ein ungef¨hres Maß f¨ r die Komplexit¨t und
a u a
Leistungsf¨higkeit des Prozessors ist. Das auf empirischen
a
Beobachtungen beruhende Gesetz von Moore besagt,
dass die Anzahl der Transistoren eines Prozessorchips sich
alle 18 bis 24 Monate verdoppelt. Diese Beobachtung wurde
1965 von Gordon Moore zum ersten Mal gemacht und gilt
nun seit uber 40 Jahren. Ein typischer Prozessorchip aus
¨
dem Jahr 2007 besteht aus ca. 200-400 Millionen Transis-
toren: beispielsweise besteht ein Intel Core 2 Duo Prozessor
10. 2 1 Kurz¨berblick Multicore-Prozessoren
u
aus ca. 291 Millionen Transistoren, ein IBM Cell-Prozessor
aus ca. 250 Millionen Transistoren.
Die Erh¨hung der Transistoranzahl ging in der Ver-
o
gangenheit mit einer Erh¨hung der Taktrate einher. Dies
o
steigerte die Verarbeitungsgeschwindigkeit der Prozesso-
ren und die Taktrate eines Prozessors wurde oftmals als
alleiniges Merkmal f¨ r dessen Leistungsf¨higkeit wahrge-
u a
nommen. Gemeinsam f¨ hrte die Steigerung der Taktrate
u
und der Transistoranzahl zu einer durchschnittlichen j¨hr-
a
lichen Leistungssteigerung der Prozessoren von ca. 55%
(bei Integer-Operationen) bzw. 75% (bei Floating-Point-
Operationen), was durch entsprechende Benchmark-Pro-
gramme gemessen wurde, siehe [32] und www.spec.org f¨ r u
eine Beschreibung der oft verwendeten SPEC-Benchmarks.
Eine Erh¨hung der Taktrate im bisherigen Umfang ist je-
o
doch f¨ r die Zukunft nicht zu erwarten. Dies ist darin be-
u
gr¨ ndet, dass mit einer Erh¨hung der Taktrate auch die
u o
Leistungsaufnahme, also der Energieverbrauch des Prozes-
sors, ansteigt, wobei ein Großteil des verbrauchten Stroms
in W¨rme umgewandelt wird und uber L¨ fter abgef¨ hrt
a u u
¨
werden muss. Das Gesetz von Moore scheint aber bis auf
weiteres seine G¨ ltigkeit zu behalten.
u
Die steigende Anzahl verf¨ gbarer Transistoren wurde
u
in der Vergangenheit f¨ r eine Vielzahl weiterer architekto-
u
nischer Verbesserungen genutzt, die die Leistungsf¨higkeit
a
der Prozessoren erheblich gesteigert hat. Dazu geh¨ren u.a.
o
• die Erweiterung der internen Wortbreite auf 64 Bits,
• die Verwendung interner Pipelineverarbeitung f¨ r die
u
ressourcenoptimierte Ausf¨ hrung aufeinanderfolgender
u
Maschinenbefehle,
• die Verwendung mehrerer Funktionseinheiten, mit de-
nen voneinander unabh¨ngige Maschinenbefehle paral-
a
lel zueinander abgearbeitet werden k¨nnen und
o
11. 1.1 Entwicklung der Mikroprozessoren 3
• die Vergr¨ßerung der prozessorlokalen Cachespeicher.
o
Wesentliche Aspekte der Leistungssteigerung sind also
die Erh¨hung der Taktrate und der interne Einsatz paralle-
o
ler Abarbeitung von Instruktionen, z.B. durch das Duplizie-
ren von Funktionseinheiten. Die Grenzen beider Entwick-
lungen sind jedoch abzusehen: Ein weiteres Duplizieren von
Funktionseinheiten und Pipelinestufen ist zwar m¨glich,
o
bringt aber wegen vorhandener Abh¨ngigkeiten zwischen
a
den Instruktionen kaum eine weitere Leistungssteigerung.
Gegen eine weitere Erh¨hung der prozessoreigenen Taktra-
o
te sprechen mehrere Gr¨ nde [36]:
u
• Ein Problem liegt darin, dass die Speicherzugriffsge-
schwindigkeit nicht im gleichen Umfang wie die Pro-
zessorgeschwindigkeit zunimmt, was zu einer Erh¨hung
o
der Zyklenanzahl pro Speicherzugriff f¨ hrt. So brauch-
u
te z.B. um 1990 ein Intel i486 f¨ r einen Zugriff auf
u
den Hauptspeicher zwischen 6 und 8 Maschinenzyklen,
w¨hrend 2006 ein Intel Pentium Prozessor uber 220 Zy-
a ¨
klen ben¨tigt. Die Speicherzugriffszeiten stellen daher
o
einen kritischen limitierenden Faktor f¨ r eine weitere
u
Leistungssteigerung dar.
• Zum Zweiten wird die Erh¨hung der Transistoranzahl
o
durch eine erh¨hte Packungsdichte erreicht, mit der aber
o
auch eine gesteigerte W¨rmeentwicklung pro Fl¨chen-
a a
einheit verbunden ist. Diese wird zunehmend zum Pro-
blem, da die notwendige K¨ hlung entsprechend aufwen-
u
diger wird.
• Zum Dritten w¨chst mit der Anzahl der Transistoren
a
auch die prozessorinterne Leitungsl¨nge f¨ r den Signal-
a u
transport, so dass die Signallaufzeit eine wichtige Rolle
spielt. Dies sieht man an folgender Berechnung: Ein mit
3GHz getakteter Prozessor hat eine Zykluszeit von 0.33
ns = 0.33 ·10−9 sec. In dieser Zeit kann ein Signal eine
12. 4 1 Kurz¨berblick Multicore-Prozessoren
u
Entfernung von 0.33 ·10−9 s·0.3 · 109m/s ≈ 0.1m zur¨ ck-
u
legen, wenn wir die Lichtgeschwindigkeit im Vakuum als
¨
Signalgeschwindigkeit ansetzen. Je nach Ubergangsme-
dium ist die Signalgeschwindigkeit sogar deutlich nied-
riger. Damit k¨nnen die Signale in einem Takt nur ei-
o
ne relativ geringe Entfernung zur¨ cklegen, so dass der
u
Layout-Entwurf der Prozessorchips entsprechend gestal-
tet werden muss.
Um eine weitere Leistungssteigerung der Prozessoren
im bisherigen Umfang zu erreichen, setzen die Prozessor-
hersteller auf eine explizite Parallelverarbeitung innerhalb
eines Prozessors, indem mehrere logische Prozessoren von
einem physikalischen Prozessor simuliert werden oder meh-
rere vollst¨ndige, voneinander nahezu unabh¨ngige Prozes-
a a
sorkerne auf einen Prozessorchip platziert werden. Der Ein-
satz expliziter Parallelverarbeitung innerhalb eines Prozes-
sors hat weitreichende Konsequenzen f¨ r die Programmie-
u
rung: soll ein Programm von der verf¨ gbaren Leistung des
u
Multicore-Prozessors profitieren, so muss es die verf¨ gba-
u
ren Prozessorkerne entsprechend steuern und effizient aus-
nutzen. Dazu werden Techniken der parallelen Program-
mierung eingesetzt. Da die Prozessorkerne eines Prozes-
sorchips ein gemeinsames Speichersystem nutzen, sind Pro-
grammierans¨tze f¨ r gemeinsamen Adressraum geeignet.
a u
1.2 Parallelit¨t auf Prozessorebene
a
Explizite Parallelit¨t auf Prozessorebene wird durch eine
a
entsprechende Architekturorganisation des Prozessorchips
erreicht.
Eine M¨glichkeit ist die oben erw¨hnte Platzierung
o a
mehrerer Prozessorkerne mit jeweils unabh¨ngigen Ausf¨ h-
a u
rungseinheiten auf einem Prozessorchip, was als Multicore-
13. 1.2 Parallelit¨t auf Prozessorebene
a 5
Prozessor bezeichnet wird. Ein anderer Ansatz besteht
darin, mehrere Kontroll߬ sse dadurch gleichzeitig auf ei-
u
nem Prozessor oder Prozessorkern auszuf¨ hren, dass der
u
Prozessor je nach Bedarf per Hardware zwischen den Kon-
troll߬ ssen umschaltet. Dies wird als simultanes Multi-
u
threading (SMT) oder Hyperthreading (HT) bezeich-
net [43].
Bei dieser Art der Parallelit¨t werden die Kontrollfl¨ sse
a u
oft als Threads bezeichnet. Dieser Begriff und die Unter-
schiede zu Prozessen werden in den folgenden Abschnitten
n¨her erl¨utert; zun¨chst reicht es aus, einen Thread als
a a a
Kontrollfluss anzusehen, der parallel zu anderen Threads
desselben Programms ausgef¨ hrt werden kann.
u
Simultanes Multithreading (SMT)
Simultanes Multithreading basiert auf dem Duplizieren des
Prozessorbereiches zur Ablage des Prozessorzustandes auf
der Chipfl¨che des Prozessors. Zum Prozessorzustand geh¨-
a o
ren die Benutzer- und Kontrollregister sowie der Interrupt-
Controller mit seinen zugeh¨rigen Registern. Damit verh¨lt
o a
sich der physikalische Prozessor aus der Sicht des Be-
triebssystems und des Benutzerprogramms wie zwei lo-
gische Prozessoren, denen Prozesse oder Threads zur
Ausf¨ hrung zugeordnet werden k¨nnen. Diese k¨nnen von
u o o
einem oder mehreren Anwendungsprogrammen stammen.
Jeder logische Prozessor legt seinen Prozessorzustand in
einem separaten Prozessorbereich ab, so dass beim Wech-
sel zu einem anderen Thread kein aufwendiges Zwischen-
speichern des Prozessorzustandes im Speichersystem erfor-
derlich ist. Die logischen Prozessoren teilen sich fast al-
le Ressourcen des physikalischen Prozessors wie Caches,
Funktions- und Kontrolleinheiten oder Bussystem. Die Rea-
lisierung der SMT-Technologie erfordert daher nur eine ge-
14. 6 1 Kurz¨berblick Multicore-Prozessoren
u
ringf¨ gige Vergr¨ßerung der Chipfl¨che. F¨ r zwei logische
u o a u
Prozessoren w¨chst z.B. f¨ r einen Intel Xeon Prozessor die
a u
erforderliche Chip߬che um weniger als 5% [44, 67]. Die
a
gemeinsamen Ressourcen des Prozessorchips werden den
logischen Prozessoren reihum zugeteilt, so dass die logi-
schen Prozessoren simultan zur Verf¨ gung stehen. Treten
u
bei einem logischen Prozessor Wartezeiten auf, k¨nnen die
o
Ausf¨ hrungs-Ressourcen dem anderen logischen Prozessor
u
zugeordnet werden, so dass aus der Sicht des physikali-
schen Prozessors eine verbesserte Nutzung der Ressourcen
gew¨hrleistet ist.
a
Untersuchungen zeigen, dass die verbesserte Nutzung
der Ressourcen durch zwei logische Prozessoren je nach An-
wendungsprogramm Laufzeitverbesserungen zwischen 15%
und 30% bewirken kann [44]. Da alle Ressourcen des Chips
von den logischen Prozessoren geteilt werden, ist beim Ein-
satz von wesentlich mehr als zwei logischen Prozessoren f¨ r
u
die meisten Einsatzgebiete keine weitere signifikante Lauf-
zeitverbesserung zu erwarten. Der Einsatz simultanen Mul-
tithreadings wird daher voraussichtlich auf wenige logische
Prozessoren beschr¨nkt bleiben. Zum Erreichen einer Leis-
a
tungsverbesserung durch den Einsatz der SMT-Technologie
ist es erforderlich, dass das Betriebssystem in der Lage
ist, die logischen Prozessoren anzusteuern. Aus Sicht eines
Anwendungsprogramms ist es erforderlich, dass f¨ r jeden
u
logischen Prozessor ein separater Thread zur Ausf¨ hrung
u
bereitsteht, d.h. f¨ r die Implementierung des Programms
u
m¨ ssen Techniken der parallelen Programmierung einge-
u
setzt werden.
Multicore-Prozessoren
Neue Prozessorarchitekturen mit mehreren Prozessorker-
nen auf einem Prozessorchip werden schon seit vielen Jah-
15. 1.2 Parallelit¨t auf Prozessorebene
a 7
ren als die vielversprechendste Technik zur weiteren Leis-
tungssteigerung angesehen. Die Idee besteht darin, anstatt
eines Prozessorchips mit einer sehr komplexen internen Or-
ganisation mehrere Prozessorkerne mit einfacherer Organi-
sation auf dem Prozessorchip zu integrieren. Dies hat den
zus¨tzlichen Vorteil, dass der Stromverbrauch des Prozes-
a
sorchips dadurch reduziert werden kann, dass vor¨ berge-
u
hend ungenutzte Prozessorkerne abgeschaltet werden [27].
Bei Multicore-Prozessoren werden mehrere Prozessor-
kerne auf einem Prozessorchip integriert. Jeder Prozessor-
kern stellt f¨ r das Betriebssystem einen separaten logischen
u
Prozessor mit separaten Ausf¨ hrungsressourcen dar, die
u
getrennt angesteuert werden m¨ ssen. Das Betriebssystem
u
kann damit verschiedene Anwendungsprogramme parallel
zueinander zur Ausf¨ hrung bringen. So k¨nnen z.B. meh-
u o
rere Hintergrundanwendungen wie Viruserkennung, Ver-
schl¨ sselung und Kompression parallel zu Anwendungs-
u
programmen des Nutzers ausgef¨ hrt werden [58]. Es ist
u
aber mit Techniken der parallelen Programmierung auch
m¨glich, ein rechenzeitintensives Anwendungsprogramm (et-
o
wa aus dem Bereich der Computerspiele, der Bildverar-
beitung oder naturwissenschaftlicher Simulationsprogram-
me) auf mehreren Prozessorkernen parallel abzuarbeiten, so
dass die Berechnungszeit im Vergleich zu einer Ausf¨ hrung
u
auf einem Prozessorkern reduziert werden kann.
Damit k¨nnen auch Standardprogramme wie Textver-
o
arbeitungsprogramme oder Computerspiele zus¨tzliche, im
a
Hintergrund ablaufende Funktionalit¨ten zur Verf¨ gung
a u
stellen, die parallel zu den Haupt-Funktionalit¨ten auf ei-
a
nem separaten Prozessorkern durchgef¨ hrt werden und so-
u
mit f¨ r den Nutzer nicht zu wahrnehmbaren Verz¨gerun-
u o
gen f¨ hren. F¨ r die Koordination der innerhalb einer An-
u u
wendung ablaufenden unterschiedlichen Funktionalit¨ten a
16. 8 1 Kurz¨berblick Multicore-Prozessoren
u
m¨ ssen Techniken der parallelen Programmierung einge-
u
setzt werden.
1.3 Architektur von Multicore-Prozessoren
F¨ r die Realisierung von Multicore-Prozessoren gibt es ver-
u
schiedene Implementierungsvarianten, die sich in der An-
zahl der Prozessorkerne, der Gr¨ße und Anordnung der Ca-
o
ches, den Zugriffm¨glichkeiten der Prozessorkerne auf die
o
Caches und dem Einsatz von heterogenen Komponenten
unterscheiden [37]. Dabei werden zur Zeit drei unterschied-
liche Architekturmodelle eingesetzt, von denen auch Misch-
formen auftreten k¨nnen.
o
Hierarchisches Design
Bei einem hierarchischen De-
sign teilen sich mehrere Pro-
zessorkerne mehrere Caches,
die in einer baumartigen Konfi-
Cache/Speicher
guration angeordnet sind, wo-
bei die Gr¨ße der Caches von
o
den Bl¨ttern zur Wurzel steigt.
a
Cache Cache Die Wurzel repr¨sentiert die
a
Verbindung zum Hauptspei-
cher. So kann z.B. jeder Pro-
Kern Kern Kern Kern
zessorkern einen separaten L1-
Cache haben, sich aber mit
hierarchisches Design anderen Prozessorkernen einen
L2-Cache teilen. Alle Prozes-
Abbildung 1.1. Hierarchi- sorkerne k¨nnen auf den ge-
o
sches Design. meinsamen externen Haupt-
speicher zugreifen, was eine
17. 1.3 Architektur von Multicore-Prozessoren 9
dreistufige Hierarchie ergibt. Dieses Konzept kann auf meh-
rere Stufen erweitert werden und ist in Abbildung 1.1
f¨ r drei Stufen veranschaulicht. Zus¨tzliche Untersyste-
u a
me k¨nnen die Caches einer Stufe miteinander verbinden.
o
Ein hierarchisches Design wird typischerweise f¨ r Server-
u
Konfigurationen verwendet.
Ein Beispiel f¨ r ein hierarchisches Design ist der IBM
u
Power5 Prozessor, der zwei 64-Bit superskalare Prozessor-
kerne enth¨lt, von denen jeder zwei logische Prozessoren
a
durch Einsatz von SMT simuliert. Jeder Prozessorkern hat
einen separaten L1-Cache (f¨ r Daten und Programme ge-
u
trennt) und teilt sich mit dem anderen Prozessorkern einen
L2-Cache (1.8 MB) sowie eine Schnittstelle zu einem ex-
ternen 36 MB L3-Cache. Andere Prozessoren mit hierar-
chischem Design sind die Intel Core 2 Prozessoren und die
Sun UltraSPARC T1 (Niagara) Prozessoren.
Pipeline-Design
Bei einem Pipeline-Design
werden die Daten durch meh-
rere Prozessorkerne schrittwei-
se weiterverarbeitet, bis sie
vom letzten Prozessorkern im
Speichersystem abgelegt wer-
den, vgl. Abbildung 1.2. Hoch-
spezialisierte Netzwerk-Prozes-
soren und Grafikchips arbei-
ten oft nach diesem Prinzip.
Ein Beispiel sind die X10 und
X11 Prozessoren von Xelera-
tor zur Verarbeitung von Netz-
Abbildung 1.2. Pipeline-
werkpaketen in Hochleistungs-
Design.
Routern. Der Xelerator X10q,
18. 10 1 Kurz¨berblick Multicore-Prozessoren
u
eine Variante des X10, enth¨lt z.B. 200 separate Prozes-
a
sorkerne, die in einer logischen linearen Pipeline mitein-
ander verbunden sind. Die Pakete werden dem Prozessor
uber mehrere Netzwerkschnittstellen zugef¨ hrt und dann
u
¨
durch die Prozessorkerne schrittweise verarbeitet, wobei je-
der Prozessorkern einen Schritt ausf¨ hrt. Die X11 Netz-
u
werkprozessoren haben bis zu 800 Pipeline-Prozessorkerne.
Netzwerkbasiertes Design
Bei einem netzwerkbasier-
ten Design sind die Pro-
zessorkerne und ihre lokalen
Caches oder Speicher uber ¨
ein Verbindungsnetzwerk mit
den anderen Prozessorkernen
des Chips verbunden, so dass
der gesamte Datentransfer zwi-
schen den Prozessorkernen uber
¨
das Verbindungsnetzwerk l¨uft,
a
vgl. Abbildung 1.3. Der Ein-
satz eines prozessorinternen
Netzwerkes ist insbesondere
Abbildung 1.3. Netzwerk- dann sinnvoll, wenn eine Viel-
basiertes Design. zahl von Prozessorkernen ver-
wendet werden soll. Ein netz-
werkorientiertes Design wird z.B. f¨ r den Intel Teraflop-
u
Prozessor verwendet, der im Rahmen der Intel Tera-Scale-
Initiative entwickelt wurde, vgl. unten, und in dem 80 Pro-
zessorkerne eingesetzt werden.
Weitere Entwicklungen
Das Potential der Multicore-Prozessoren wurde von vie-
len Hardwareherstellern wie Intel und AMD erkannt und
19. 1.3 Architektur von Multicore-Prozessoren 11
seit 2005 bieten viele Hardwarehersteller Prozessoren mit
zwei oder mehr Kernen an. Ab Ende 2006 liefert Intel
Quadcore-Prozessoren und ab 2008 wird mit der Auslie-
ferung von Octcore-Prozessoren gerechnet. IBM bietet mit
der Cell-Architektur einen Prozessor mit acht spezialisier-
ten Prozessorkernen, vgl. Abschnitt 1.4. Der seit Dezember
2005 ausgelieferte UltraSPARC T1 Niagara Prozessor von
Sun hat bis zu acht Prozessorkerne, von denen jeder durch
den Einsatz von simultanem Multithreading, das von Sun
als CoolThreads-Technologie bezeichnet wird, vier Thre-
ads simultan verarbeiten kann. Damit kann ein UltraS-
PARC T1 bis zu 32 Threads simultan ausf¨ hren. Das f¨ r
u u
2008 angek¨ ndigte Nachfolgemodell des Niagara-Prozessors
u
(ROCK) soll bis zu 16 Prozessorkerne enthalten.
Intel Tera-Scale-Initiative
Intel untersucht im Rahmen des Tera-scale Computing Pro-
grams die Herausforderungen bei der Herstellung und Pro-
grammierung von Prozessoren mit Dutzenden von Prozes-
sorkernen [27]. Diese Initiative beinhaltet auch die Ent-
wicklung eines Teraflop-Prozessors, der 80 Prozessorkerne
enth¨lt, die als 8×10-Gitter organisiert sind. Jeder Prozes-
a
sorkern kann Floating-Point-Operationen verarbeiten und
enth¨lt neben einem lokalen Cachespeicher auch einen Rou-
a
ter zur Realisierung des Datentransfers zwischen den Pro-
zessorkernen und dem Hauptspeicher. Zus¨tzlich kann ein
a
solcher Prozessor spezialisierte Prozessorkerne f¨ r die Ver-
u
arbeitung von Videodaten, graphischen Berechnungen und
zur Verschl¨ sselung von Daten enthalten. Je nach Einsatz-
u
gebiet kann die Anzahl der spezialisierten Prozessorkerne
variiert werden.
Ein wesentlicher Bestandteil eines Prozessors mit ei-
ner Vielzahl von Prozessorkernen ist ein effizientes Verbin-
20. 12 1 Kurz¨berblick Multicore-Prozessoren
u
dungsnetzwerk auf dem Prozessorchip, das an eine variable
Anzahl von Prozessorkernen angepasst werden kann, den
Ausfall einzelner Prozessorkerne toleriert und bei Bedarf
das Abschalten einzelner Prozessorkerne erlaubt, falls diese
f¨ r die aktuelle Anwendung nicht ben¨tigt werden. Ein sol-
u o
ches Abschalten ist insbesondere zur Reduktion des Strom-
verbrauchs sinnvoll.
F¨ r eine effiziente Nutzung der Prozessorkerne ist ent-
u
scheidend, dass die zu verarbeitenden Daten schnell zu den
Prozessorkernen transportiert werden k¨nnen, so dass diese
o
nicht auf die Bereitstellung der Daten warten m¨ ssen. Dazu
u
sind ein leistungsf¨higes Speichersystem und I/O-System
a
erforderlich. Das Speichersystem setzt private L1-Caches
ein, auf die nur von jeweils einem Prozessorkern zugegriffen
werden kann, sowie gemeinsame, evtl. aus mehreren Stufen
bestehende L2-Caches ein, die Daten verschiedener Prozes-
sorkerne enthalten. F¨ r einen Prozessorchip mit Dutzenden
u
von Prozessorkernen muss voraussichtlich eine weitere Stufe
im Speichersystem eingesetzt werden [27]. Das I/O-System
muss in der Lage sein, Hunderte von Gigabytes pro Sekun-
de zum Prozessorchip zu transportieren. Hier arbeitet z.B.
Intel an der Entwicklung geeigneter Systeme.
¨
Tabelle 1.1 gibt einen Uberblick uber aktuelle Multicore-
¨
Prozessoren. Zu bemerken ist dabei, dass der Sun Ul-
traSPARC T1-Prozessor im Gegensatz zu den drei ande-
ren Prozessoren kaum Unterst¨ tzung f¨ r Floating-Point-
u u
Berechnungen bietet und somit uberwiegend f¨ r den Ein-
u
¨
satz im Serverbereich, wie Web-Server oder Applikations-
Server, geeignet ist. F¨ r eine detailliertere Behandlung der
u
Architektur von Multicore-Prozessoren und weiterer Bei-
spiele verweisen wir auf [10, 28].
21. 1.4 Beispiele 13
¨
Tabelle 1.1. Uberblick uber verschiedene Multicore-Prozessoren,
¨
vgl. auch [28].
Intel IBM AMD Sun
Prozessor Core 2 Duo Power 5 Opteron T1
Prozessorkerne 2 2 2 8
Instruktionen 4 4 3 1
pro Zyklus
SMT nein ja nein ja
L1-Cache I/D 32/32 64/32 64/64 16/8
in KB per core
L2-Cache 4 MB 1.9 MB 1 MB 3 MB
shared shared per core shared
Taktrate (GHz) 2.66 1.9 2.4 1.2
Transistoren 291 Mio 276 Mio 233 Mio 300 Mio
Stromverbrauch 65 W 125 W 110 W 79 W
1.4 Beispiele
Im Folgenden wird die Architektur von Multicore-Prozes-
soren anhand zweier Beispiele verdeutlicht: der Intel Core
2 Duo-Architektur und dem IBM Cell-Prozessor.
Intel Core 2 Prozessor
Intel Core 2 bezeichnet eine Familie von Intel-Prozessoren
mit ¨hnlicher Architektur. Die Intel Core-Architektur ba-
a
siert auf einer Weiterentwicklung der Pentium M Prozesso-
ren, die viele Jahre im Notebookbereich eingesetzt wurden.
Die neue Architektur l¨st die bei den Pentium 4 Prozesso-
o
ren noch eingesetzte NetBurst-Architektur ab. Signifikante
Merkmale der neuen Architektur sind:
22. 14 1 Kurz¨berblick Multicore-Prozessoren
u
• eine drastische Verk¨ rzung der internen Pipelines (ma-
u
ximal 14 Stufen anstatt maximal 31 Stufen bei der
NetBurst-Architektur), damit verbunden
• eine Reduktion der Taktrate und damit verbunden auch
• eine deutliche Reduktion des Stromverbrauchs: die Re-
duktion des Stromverbrauches wird auch durch eine
Power-Management-Einheit unterst¨ tzt, die das zeit-
u
weise Ausschalten ungenutzter Prozessorteile erm¨glicht
o
[48] und
• die Unterst¨ tzung neuer Streaming-Erweiterungen (Stre-
u
aming SIMD Extensions, SSE).
Intel Core 2 Prozessoren werden zur Zeit (August 2007)
als Core 2 Duo bzw. Core 2 Quad Prozessoren mit 2 bzw.
4 unabh¨ngigen Prozessorkernen in 65nm-Technologie ge-
a
fertigt. Im Folgenden wird der Core 2 Duo Prozessor kurz
beschrieben [24]. Die Core 2 Quad Prozessoren haben einen
ahnlichen Aufbau, enthalten aber 4 statt 2 Prozessorkerne.
¨
Da die Core 2 Prozessoren auf der Technik des Pentium
M Prozessors basieren, unterst¨ tzen sie kein Hyperthrea-
u
ding. Die allgemeine Struktur der Core 2 Duo Architektur
ist in Abb. 1.4 wiedergegeben. Der Prozessorchip enth¨lt a
zwei unabh¨ngige Prozessorkerne, von denen jeder separate
a
L1-Caches anspricht; diese sind f¨ r Instruktionen (32K) und
u
Daten (32K) getrennt realisiert. Der L2-Cache (4 MB) ist
dagegen nicht exklusiv und wird von beiden Prozessorker-
nen gemeinsam f¨ r Instruktionen und Daten genutzt. Alle
u
Zugriffe von den Prozessorkernen und vom externen Bus auf
den L2-Cache werden von einem L2-Controller behandelt.
F¨ r die Sicherstellung der Koh¨renz der auf den verschie-
u a
denen Stufen der Speicherhierarchie abgelegten Daten wird
ein MESI-Protokoll (Modified, Exclusive, Shared, Invalid)
verwendet, vgl. [17, 47, 59] f¨ r eine detaillierte Erkl¨rung.
u a
Alle Daten- und I/O-Anfragen zum oder vom externen Bus
23. 1.4 Beispiele 15
(Front Side Bus) werden uber einen Bus-Controller gesteu-
¨
ert.
Core 2 Duo Prozessor
Core 0 Core 1
Architektur−Ressourcen Architektur−Ressourcen
Ausführungs−Ressourcen Ausführungs−Ressourcen
L1−Caches (I/O) L1−Caches (I/O)
Cache−Controller Cache−Controller
Power−Management−Controller
L2−Cache mit Controller (shared)
Bus−Interface und −Controller
FrontSideBus
¨
Abbildung 1.4. Uberblick Core 2 Duo Architektur.
Ein wichtiges Element ist die Kontrolleinheit f¨ r den
u
Stromverbrauch des Prozessors (Power Management Con-
troller) [48], die den Stromverbrauch des Prozessorchips
durch Reduktion der Taktrate der Prozessorenkerne oder
durch Abschalten (von Teilen) des L2-Caches reduzieren
kann.
Jeder Prozessorkern f¨ hrt einen separaten Strom von
u
Instruktionen aus, der sowohl Berechnungs- als auch Spei-
cherzugriffsinstruktionen (load/store) enthalten kann. Da-
bei kann jeder der Prozessorkerne bis zu vier Instruktionen
gleichzeitig verarbeiten. Die Prozessorkerne enthalten sepa-
rate Funktionseinheiten f¨ r das Laden bzw. Speichern von
u
24. 16 1 Kurz¨berblick Multicore-Prozessoren
u
Daten, die Ausf¨ hrung von Integeroperationen (durch ei-
u
ne ALU, arithmetic logic unit), Floating-Point-Operationen
sowie SSE-Operationen. Instruktionen k¨nnen aber nur
o
dann parallel zueinander ausgef¨ hrt werden, wenn keine
u
Abh¨ngigkeiten zwischen ihnen bestehen. F¨ r die Steue-
a u
rung der Ausf¨ hrung werden komplexe Schedulingverfah-
u
ren eingesetzt, die auch eine Umordnung von Instruktionen
(out-of-order execution) erlauben, um eine m¨glichst gute
o
Ausnutzung der Funktionseinheiten zu verwirklichen [28].
Laden von Instruktionen
Instruktionsschlange
Mikrocode Dekodiereinheit L2−
ROM Cache
(shared)
Register−Umbenennung und −Allokierung
Umordnungspuffer
Instruktions−Scheduler
ALU ALU ALU Load Store
Branch FPAdd FPMul
MMX/SSE MMX/SSE MMX/SSE
Speicherzugriffspuffer
FPMove FPMove FPMove
L1−Datencache
Abbildung 1.5. Instruktionsverarbeitung und Speicherorganisa-
tion eines Prozessorkerns des Intel Core 2 Prozessors.
Abbildung 1.5 veranschaulicht die Organisation der Ab-
arbeitung von Instruktionen durch einen der Prozessorker-
ne [20]. Jeder der Prozessorkerne l¨dt x86-Instruktionen
a
in eine Instruktionsschlange, auf die die Dekodiereinheit
zugreift und die Instruktionen in Mikroinstruktionen zer-
25. 1.4 Beispiele 17
legt. F¨ r komplexere x86-Instruktionen werden die zu-
u
geh¨rigen Mikroinstruktionen uber einen ROM-Speicher
o ¨
geladen. Die Mikroinstruktionen werden vom Instruktions-
Scheduler freien Funktionseinheiten zugeordnet, wobei die
Instruktionen in einer gegen¨ ber dem urspr¨ nglichen Pro-
u u
grammcode ge¨nderten Reihenfolge abgesetzt werden k¨n-
a o
nen. Alle Speicherzugriffsoperationen werden uber den L1-
¨
Datencache abgesetzt, der Integer-und Floating-Point-Da-
ten enth¨lt.
a
F¨ r Ende 2007 bzw. Anfang 2008 sollen Intel Core 2-
u
Prozessoren mit verbesserter Core-Architektur eingef¨ hrt
u
werden (Codename Penryn). Voraussichtlich f¨ r Ende 2008
u
ist eine neue Generation von Intel-Prozessoren geplant, die
auf einer neuen Architektur basiert (Codename Nehalem).
Diese neuen Prozessoren sollen neben mehreren Prozessor-
kernen (zu Beginn acht) auch einen Graphikkern und einen
Speichercontroller auf einem Prozessorchip integrieren. Die
neuen Prozessoren sollen auch wieder die SMT-Technik (si-
multanes Multithreading) unterst¨ tzen, so dass auf jedem
u
Prozessorkern gleichzeitig zwei Threads ausgef¨ hrt werden
u
k¨nnen. Diese Technik wurde teilweise f¨ r Pentium 4 Pro-
o u
zessoren verwendet, nicht jedoch f¨ r die Core 2 Duo und
u
Quad Prozessoren.
IBM Cell-Prozessor
Der Cell-Prozessor wurde von IBM in Zusammenarbeit
mit Sony und Toshiba entwickelt. Der Prozessor wird u.a.
von Sony in der Spielekonsole PlayStation 3 eingesetzt,
siehe [39, 34] f¨ r ausf¨ hrlichere Informationen. Der Cell-
u u
Prozessor enth¨lt ein Power Processing Element (PPE) und
a
8 Single-Instruction Multiple-Datastream (SIMD) Prozesso-
ren. Das PPE ist ein konventioneller 64-Bit-Mikroprozessor
auf der Basis der Power-Architektur von IBM mit relativ
26. 18 1 Kurz¨berblick Multicore-Prozessoren
u
einfachem Design: der Prozessor kann pro Takt zwei In-
struktionen absetzen und simultan zwei unabh¨ngige Thre-
a
ads ausf¨ hren. Die einfache Struktur hat den Vorteil, dass
u
trotz hoher Taktrate eine geringe Leistungsaufnahme re-
sultiert. F¨ r den gesamten Prozessor ist bei einer Taktrate
u
von 3.2 GHz nur eine Leistungsaufnahme von 60-80 Watt
erforderlich.
Auf der Chip߬che des Cell-Prozessors sind neben dem
a
PPE acht SIMD-Prozessoren integriert, die als SPE (Syn-
ergetic Processing Element) bezeichnet werden. Jedes SPE
stellt einen unabh¨ngigen Vektorprozessor mit einem 256KB
a
großen lokalem SRAM-Speicher dar, der als Local Store
(LS) bezeichnet wird. Das Laden von Daten in den LS und
das Zur¨ ckspeichern von Resultaten aus dem LS in den
u
Hauptspeicher muss per Software erfolgen.
Jedes SPE enth¨lt 128 128-Bit-Register, in denen die
a
Operanden von Instruktionen abgelegt werden k¨nnen. Da
o
auf die Daten in den Registern sehr schnell zugegriffen wer-
den kann, reduziert die große Registeranzahl die Notwen-
digkeit von Zugriffen auf den LS und f¨ hrt damit zu ei-
u
ner geringen mittleren Speicherzugriffszeit. Jedes SPE hat
vier Floating-Point-Einheiten (32 Bit) und vier Integer-
Einheiten. Z¨hlt man eine Multiply-Add-Instruktion als
a
zwei Operationen, kann jedes SPE bei 3.2 GHz Taktrate pro
Sekunde uber 25 Milliarden Floating-Point-Operationen
¨
(25.6 GFlops) und uber 25 Milliarden Integer-Operationen
¨
(25.6 Gops) ausf¨ hren. Da ein Cell-Prozessor acht SPE
u
enth¨lt, f¨ hrt dies zu einer maximalen Performance von
a u
uber 200 GFlops, wobei die Leistung des PPE noch nicht
¨
ber¨ cksichtigt wurde. Eine solche Leistung kann allerdings
u
nur bei guter Ausnutzung der LS-Speicher und effizienter
Zuordnung von Instruktionen an Funktionseinheiten der
SPE erreicht werden. Zu beachten ist auch, dass sich diese
Angabe auf 32-Bit Floating-Point-Zahlen bezieht. Der Cell-
27. 1.4 Beispiele 19
Prozessor kann durch Zusammenlegen von Funktionseinhei-
ten auch 64-Bit Floating-Point-Zahlen verarbeiten, dies re-
sultiert aber in einer wesentlich geringeren maximalen Per-
formance. Zur Vereinfachung der Steuerung der SPEs und
zur Vereinfachung des Schedulings verwenden die SPEs in-
tern keine SMT-Technik.
Die zentrale Verbindungseinheit des Cell-Prozessors ist
ein Bussystem, der sogenannte Element Interconnect Bus
(EIB). Dieser besteht aus vier unidirektionalen Ringver-
bindungen, die eine Wortbreite von 16 Bytes haben und
mit der halben Taktrate des Prozessors arbeiten. Zwei der
Ringe werden in entgegengesetzter Richtung zu den ande-
ren beiden Ringe betrieben, so dass die maximale Latenz
im schlechtesten Fall durch einen halben Ringdurchlauf be-
stimmt wird. F¨ r den Transport von Daten zwischen be-
u
nachbarten Ringelementen k¨nnen maximal drei Transfer-
o
operationen simultan durchgef¨ hrt werden, f¨ r den Zyklus
u u
des Prozessors ergibt dies 16 · 3/2 = 24 Bytes pro Zyklus.
F¨ r die vier Ringverbindungen ergibt dies eine maxima-
u
le Transferrate von 96 Bytes pro Zyklus, woraus bei einer
Taktrate von 3.2 GHz eine maximale Transferrate von uber
¨
300 GBytes/Sekunde resultiert. Abbildung 1.6 zeigt einen
schematischen Aufbau des Cell-Prozessors mit den bisher
beschriebenen Elementen sowie dem Speichersystem (Me-
mory Interface Controller, MIC) und dem I/O-System (Bus
Interface Controller, BIC). Das Speichersystem unterst¨ tzt
u
die XDR-Schnittstelle von Rambus. Das I/O-System un-
terst¨ tzt das Rambus RRAC (Redwood Rambus Access
u
Cell) Protokoll.
Zum Erreichen einer guten Leistung ist es wichtig, die
SPEs des Cell-Prozessors effizient zu nutzen. Dies kann f¨ r
u
spezialisierte Programme, wie z.B. Videospiele, durch di-
rekte Verwendung von SPE-Assembleranweisungen erreicht
werden. Da dies f¨ r die meisten Anwendungsprogramme
u
28. 20 1 Kurz¨berblick Multicore-Prozessoren
u
Synergetic Processing Elements
SPU SPU SPU SPU SPU SPU SPU SPU
LS LS LS LS LS LS LS LS
16B/
Zyklus
EIB (bis 96 B/Zyklus)
L2
MIC BIC
L1 PPU
Dual RRAC I/O
64−Bit Power Architektur XDR
Abbildung 1.6. Schematischer Aufbau des Cell-Prozessors.
zu aufwendig ist, werden f¨ r das Erreichen einer guten
u
Gesamtleistung eine effektive Compilerunterst¨ tzung sowie
u
die Verwendung spezialisierter Programmbibliotheken z.B.
zur Verwaltung von Taskschlangen wichtig sein.
29. 2
Konzepte paralleler
Programmierung
Die Leistungsverbesserung der Generation der Multicore-
Prozessoren wird technologisch durch mehrere Prozessor-
kerne auf einem Chip erreicht. Im Gegensatz zu bisherigen
Leistungsverbesserungen bei Prozessoren hat diese Tech-
nologie jedoch Auswirkungen auf die Softwareentwicklung:
Konnten bisherige Verbesserungen der Prozessorhardware
zu Leistungsgewinnen bei existierenden (sequentiellen) Pro-
grammen f¨ hren, ohne dass die Programme ge¨ndert wer-
u a
den mussten, so ist zur vollen Ausnutzung der Leistung
der Multicore-Prozessoren ein Umdenken hin zur paralle-
len Programmierung notwendig [62].
Parallele Programmiertechniken sind seit vielen Jahren
im Einsatz, etwa im wissenschaftlichen Rechnen auf Paral-
lelrechnern oder im Multithreading, und stellen somit kei-
nen wirklich neuen Programmierstil dar. Neu hingegen ist,
dass durch die k¨ nftige Allgegenw¨rtigkeit der Multicore-
u a
Prozessoren ein Ausbreiten paralleler Programmiertechni-
ken in alle Bereiche der Softwareentwicklung erwartet wird
und diese damit zum R¨ stzeug eines jeden Softwareentwick-
u
lers geh¨ren werden.
o
30. 22 2 Konzepte paralleler Programmierung
Ein wesentlicher Schritt in der Programmierung von
Multicore-Prozessoren ist das Bereitstellen mehrerer Be-
rechnungsstr¨me, die auf den Kernen eines Multicore-Pro-
o
zessors simultan, also gleichzeitig, abgearbeitet werden. Zu-
n¨chst ist die rein gedankliche Arbeit durchzuf¨ hren, einen
a u
einzelnen Anwendungsalgorithmus in solche Berechnungs-
str¨me zu zerlegen, was eine durchaus langwierige, schwie-
o
rige und kreative Aufgabe sein kann, da es eben sehr viele
M¨glichkeiten gibt, dies zu tun, und insbesondere korrekte
o
und effiziente Software resultieren soll.
Zur Erstellung der parallelen Software sind einige Grund-
begriffe und -kenntnisse hilfreich:
• Wie wird beim Entwurf eines parallelen Programmes
vorgegangen?
• Welche Eigenschaften der parallelen Hardware sollen zu
Grunde gelegt werden?
• Welches parallele Programmiermodell soll genutzt wer-
den?
• Wie kann der Leistungsvorteil des parallelen Programms
gegen¨ ber dem sequentiellen bestimmt werden?
u
• Welche parallele Programmierumgebung oder -sprache
soll genutzt werden?
2.1 Entwurf paralleler Programme
Die Grundidee der parallelen Programmierung besteht dar-
in, mehrere Berechnungsstr¨me zu erzeugen, die gleichzei-
o
tig, also parallel, ausgef¨ hrt werden k¨nnen und durch ko-
u o
ordinierte Zusammenarbeit eine gew¨nschte Aufgabe er-
u
ledigen. Liegt bereits ein sequentielles Programm vor, so
spricht man auch von der Parallelisierung eines Program-
mes.
31. 2.1 Entwurf paralleler Programme 23
Zur Erzeugung der Berechnungsstr¨me wird die aus-
o
zuf¨ hrende Aufgabe in Teilaufgaben zerlegt, die auch Tasks
u
genannt werden. Tasks sind die kleinsten Einheiten der Par-
allelit¨t. Beim Entwurf der Taskstruktur eines Program-
a
mes m¨ ssen Daten- und Kontrollabh¨ngigkeiten beachtet
u a
und eingeplant werden, um ein korrektes paralleles Pro-
gramm zu erhalten. Die Gr¨ße der Tasks wird Granu-
o
larit¨t genannt. F¨ r die tats¨chliche parallele Abarbei-
a u a
tung werden die Teilaufgaben in Form von Threads oder
Prozessen auf physikalische Rechenressourcen abgebildet.
Die Rechenressourcen k¨nnen Prozessoren eines Paral-
o
lelrechners, aber auch die Prozessorkerne eines Multicore-
Prozessors sein.
Die Zuordnung von Tasks an Prozesse oder Threads
wird auch als Scheduling bezeichnet. Dabei kann man
zwischen statischem Scheduling, bei dem die Zuteilung
beim Start des Programms festgelegt wird, und dynami-
schem Scheduling, bei dem die Zuteilung w¨hrend der
a
Abarbeitung des Programms erfolgt, unterscheiden. Die
Abbildung von Prozessen oder Threads auf Prozessorker-
ne, auch Mapping genannt, kann explizit im Programm
bzw. durch das Betriebssystem erfolgen. Abbildung 2.1
zeigt eine Veranschaulichung.
Software mit mehreren parallel laufenden Tasks gibt es
in vielen Bereichen schon seit Jahren. So bestehen Server-
anwendungen h¨ufig aus mehreren Threads oder Prozes-
a
sen. Ein typisches Beispiel ist ein Webserver, der mit ei-
nem Haupt-Thread HTTP-Anfragenachrichten von belie-
bigen Clients (Browsern) entgegennimmt und f¨ r jede ein-
u
treffende Verbindungsanfrage eines Clients einen separa-
ten Thread erzeugt. Dieser Thread behandelt alle von die-
sem Client eintreffenden HTTP-Anfragen und schickt die
zugeh¨rigen HTTP-Antwortnachrichten uber eine Client-
o ¨
spezifische TCP-Verbindung. Wird diese TCP-Verbindung
32. 24 2 Konzepte paralleler Programmierung
Prozessor−
Tasks Threads Kerne
T1 T2
Schedu− T1
ling Mapping P1
T2
T3
Thread−
Task−
T3 P2
Zerlegung Zuordnung
Abbildung 2.1. Veranschaulichung der typischen Schritte zur
Parallelisierung eines Anwendungsalgorithmus. Der Algorithmus
wird in der Zerlegungsphase in Tasks mit gegenseitigen Abh¨ngig-
a
keiten aufgespalten. Diese Tasks werden durch das Scheduling
Threads zugeordnet, die auf Prozessorkerne abgebildet werden.
geschlossen, wird auch der zugeh¨rige Thread beendet.
o
Durch dieses Vorgehen kann ein Webserver gleichzeitig vie-
le ankommende Anfragen nebenl¨ufig erledigen oder auf
a
verf¨ gbaren Rechenressourcen parallel bearbeiten. F¨ r Web-
u u
server mit vielen Anfragen (wie google oder ebay) werden
entsprechende Plattformen mit vielen Rechenressourcen be-
reitgehalten.
Abarbeitung paralleler Programme
F¨ r die parallele Abarbeitung der Tasks bzw. Threads oder
u
Prozesse gibt es verschiedene Ans¨tze, vgl. z.B. auch [3]:
a
• Multitasking: Multitasking-Betriebssysteme arbeiten
mehrere Threads oder Prozesse in Zeitscheiben auf dem-
selben Prozessor ab. Hierdurch k¨nnen etwa die Latenz-
o
zeiten von I/O-Operationen durch eine verschachtelte
Abarbeitung der Tasks uberdeckt werden. Diese Form
¨
33. 2.1 Entwurf paralleler Programme 25
der Abarbeitung mehrerer Tasks wird als Nebenl¨ufig-
a
keit (Concurrency) bezeichnet; mehrere Tasks werden
gleichzeitig bearbeitet, aber nur eine Task macht zu ei-
nem bestimmten Zeitpunkt einen tats¨chlichen Rechen-
a
fortschritt. Eine simultane parallele Abarbeitung findet
also nicht statt.
• Multiprocessing: Die Verwendung mehrerer physi-
kalischer Prozessoren macht eine tats¨chliche paralle-
a
le Abarbeitung mehrerer Tasks m¨glich. Bedingt durch
o
die hardwarem¨ßige Parallelit¨t mit mehreren physika-
a a
lischen Prozessoren kann jedoch ein nicht unerheblicher
zeitlicher Zusatzaufwand (Overhead) entstehen.
• Simultanes Multithreading (SMT): Werden meh-
rere logische Prozessoren auf einem physikalischen Pro-
zessor ausgef¨ hrt, so k¨nnen die Hardwareressourcen ei-
u o
nes Prozessors besser genutzt werden und es kann eine
teilweise beschleunigte Abarbeitung von Tasks erfolgen,
vgl. Kap. 1. Bei zwei logischen Prozessoren sind Leis-
tungssteigerungen durch Nutzung von Wartezeiten ei-
nes Threads f¨ r die Berechnungen des anderen Threads
u
um bis zu 30 % m¨glich.
o
• Chip-Multiprocessing: Der n¨chste Schritt ist nun,
a
die Idee der Threading-Technologie auf einem Chip mit
dem Multiprocessing zu verbinden, was durch Multicore-
Prozessoren m¨glich ist. Die Programmierung von Mul-
o
ticore-Prozessoren vereint das Multiprocessing mit dem
simultanen Multithreading in den Sinne, dass Multi-
threading-Programme nicht nebenl¨ufig sondern tat-
a
s¨chlich parallel auf einen Prozessor abgearbeitet wer-
a
den. Dadurch sind im Idealfall Leistungssteigerungen
bis zu 100 % f¨ r einen Dualcore-Prozessor m¨glich.
u o
F¨ r die Programmierung von Multicore-Prozessoren wer-
u
den Multithreading-Programme eingesetzt. Obwohl viele
34. 26 2 Konzepte paralleler Programmierung
moderne Programme bereits Multithreading verwenden,
gibt es doch Unterschiede, die gegen¨ ber der Programmie-
u
rung von Prozessoren mit simultanem Multithreading zu
beachten sind:
• Einsatz zur Leistungsverbesserung: Die Leistungsver-
besserungen von SMT-Prozessoren wird meistens zur
Verringerung der Antwortzeiten f¨ r den Nutzer ein-
u
gesetzt, indem etwa ein Thread zur Beantwortung ei-
ner oder mehrerer Benutzeranfragen abgespalten und
nebenl¨ufig ausgef¨ hrt wird. In Multicore-Prozessoren
a u
hingegen wird die gesamte Arbeit eines Programmes
durch Partitionierung auf die einzelnen Kerne verteilt
und gleichzeitig abgearbeitet.
• Auswirkungen des Caches: Falls jeder Kern eines Mul-
ticore-Prozessors einen eigenen Cache besitzt, so kann
es zu dem beim Multiprocessing bekannten False Sha-
ring kommen. Bei False Sharing handelt es sich um das
Problem, dass zwei Kerne gleichzeitig auf Daten arbei-
ten, die zwar verschieden sind, jedoch in derselben Ca-
chezeile liegen. Obwohl die Daten also unabh¨ngig sind,
a
wird die Cachezeile im jeweils anderen Kern als ung¨ ltig
u
markiert, wodurch es zu Leistungsabfall kommt.
• Thread-Priorit¨ten: Bei der Ausf¨ hrung von Multithrea-
a u
ding-Programmen auf Prozessoren mit nur einem Kern
wird immer der Thread mit der h¨chsten Priorit¨t zu-
o a
erst bearbeitet. Bei Prozessoren mit mehreren Kernen
k¨nnen jedoch auch Threads mit unterschiedlichen Prio-
o
rit¨ten gleichzeitig abgearbeitet werden, was zu durch-
a
aus unterschiedlichen Resultaten f¨ hren kann.
u
Diese Beispiele zeigen, dass f¨ r den Entwurf von Multi-
u
threading-Programmen f¨ r Multicore-Prozessoren nicht nur
u
die Techniken der Threadprogrammierung gebraucht wer-
den, sondern Programmiertechniken, Methoden und Design-
35. 2.2 Klassifizierung paralleler Architekturen 27
entscheidungen der parallelen Programmierung eine erheb-
liche Rolle spielen.
2.2 Klassifizierung paralleler Architekturen
Unter paralleler Hardware wird Hardware zusammenge-
fasst, die mehrere Rechenressourcen bereitstellt, auf denen
ein Programm in Form mehrerer Berechnungsstr¨me abge-
o
arbeitet wird. Die Formen paralleler Hardware reichen also
von herk¨mmlichen Parallelrechnern bis hin zu parallelen
o
Rechenressourcen auf einem Chip, wie z.B. bei Multicore-
Prozessoren. Eine erste Klassifizierung solcher paralleler
Hardware hat bereits Flynn in der nach ihm benannten
Flynnschen Klassifikation gegeben [23]. Diese Klassi-
fikation unterteilt parallele Hardware in vier Klassen mit
unterschiedlichen Daten- und Kontroll߬ ssen:
u
• Die SISD (Single Instruction, Single Data) Rechner be-
sitzen eine Rechenressource, einen Datenspeicher und
einen Programmspeicher, entsprechen also dem klassi-
schen von-Neumann-Rechner der sequentiellen Pro-
grammierung.
• Die MISD (Multiple Instruction, Single Data) Rechner
stellen mehrere Rechenressourcen, aber nur einen Pro-
grammspeicher bereit. Wegen der geringen praktischen
Relevanz spielt diese Klasse keine wesentliche Rolle.
• Die SIMD (Single Instruction, Multiple Data) Rech-
ner bestehen aus mehreren Rechenressourcen mit jeweils
separatem Zugriff auf einen Datenspeicher, aber nur ei-
nem Programmspeicher. Jede Ressource f¨ hrt dieselben
u
Instruktionen aus, die aus dem Programmspeicher gela-
den werden, wendet diese aber auf unterschiedliche Da-
ten an. F¨ r diese Klasse wurden in der Vergangenheit
u
Parallelrechner konstruiert und genutzt.
36. 28 2 Konzepte paralleler Programmierung
• Die MIMD (Multiple Instruction, Multiple Data) Rech-
ner sind die allgemeinste Klasse und zeichnen sich durch
mehrere Rechenressourcen mit jeweils separatem Zugriff
auf einen Datenspeicher und jeweils lokalen Programm-
speichern aus. Jede Rechenressource kann also unter-
schiedliche Instruktionen auf unterschiedlichen Daten
verarbeiten.
Zur Klasse der MIMD-Rechner geh¨ren viele der heu-
o
te aktuellen Parallelrechner, Cluster von PCs aber auch
Multicore-Prozessoren, wobei die einzelnen Prozessoren,
die PCs des Clusters oder die Kerne auf dem Chip ei-
nes Multicore-Prozessors die jeweiligen Rechenressourcen
bilden. Dies zeigt, dass die Flynnsche Klassifizierung f¨ r
u
die heutige Vielfalt an parallelen Rechenressourcen zu grob
ist und weitere Unterteilungen f¨ r den Softwareentwickler
u
n¨ tzlich sind. Eine der weiteren Unterschiede der Hardware
u
von MIMD-Rechnern ist die Speicherorganisation, die sich
auf den Zugriff der Rechenressourcen auf die Daten eines
Programms auswirkt:
Rechner mit verteiltem Speicher bestehen aus Re-
chenressourcen, die jeweils einen ihnen zugeordneten lo-
kalen bzw. privaten Speicher haben. Auf Daten im loka-
len Speicher hat jeweils nur die zugeordnete Rechenres-
source Zugriff. Werden Daten aus einem Speicher ben¨tigt,
o
der zu einer anderen Rechenressource lokal ist, so werden
Programmiermechanismen, wie z. B. Kommunikation uber ¨
ein Verbindungsnetzwerk, eingesetzt. Clustersysteme, aber
auch viele Parallelrechner geh¨ren in diese Klasse.
o
Rechner mit gemeinsamem Speicher bestehen aus
mehreren Rechenressourcen und einem globalen oder ge-
meinsamen Speicher, auf den alle Rechenressourcen uber ¨
ein Verbindungsnetzwerk auf Daten zugreifen k¨nnen. Da-
o
durch kann jede Rechenressource die gesamten Daten des
37. 2.3 Parallele Programmiermodelle 29
parallelen Programms zugreifen und verarbeiten. Server-
Architekturen und insbesondere Multicore-Prozessoren ar-
beiten mit einem physikalisch gemeinsamen Speicher.
Die durch die Hardware gegebene Organisation des
Speichers in verteilten und gemeinsamen Speicher kann f¨ r u
den Programmierer in Form privater oder gemeinsamer Va-
riable sichtbar und nutzbar sein. Es ist prinzipiell jedoch
mit Hilfe entsprechender Softwareunterst¨ tzung m¨glich,
u o
das Programmieren mit gemeinsamen Variablen (shared va-
riables) auch auf physikalisch verteiltem Speicher bereitzu-
stellen. Ebenso kann die Programmierung mit verteiltem
Adressraum und Kommunikation auf einem physikalisch
gemeinsamen Speicher durch zus¨tzliche Software m¨glich
a o
sein. Dies ist nur ein Beispiel daf¨ r, dass die gegebene Hard-
u
ware nur ein Teil dessen ist, was dem Softwareentwickler als
Sicht auf ein paralleles System dient.
2.3 Parallele Programmiermodelle
Der Entwurf eines parallelen Programmes basiert immer
auch auf einer abstrakten Sicht auf das parallele System,
auf dem die parallele Software abgearbeitet werden soll.
Diese abstrakte Sicht wird paralleles Programmiermo-
dell genannt und setzt sich aus mehr als nur der gege-
benen parallelen Hardware zusammen: Ein paralleles Pro-
grammiermodell beschreibt ein paralleles Rechensystem aus
der Sicht, die sich dem Softwareentwickler durch System-
software wie Betriebssystem, parallele Programmiersprache
oder -bibliothek, Compiler und Laufzeitbibliothek bietet.
Entsprechend viele durchaus unterschiedliche parallele Pro-
grammiermodelle bieten sich dem Softwareentwickler an.
Folgende Kriterien erlauben jedoch eine systematische Her-
38. 30 2 Konzepte paralleler Programmierung
angehensweise an diese Vielfalt der Programmiermodelle
[59]:
• Auf welcher Ebene eines Programmes sollen parallele
Programmteile ausgef¨ hrt werden? (z.B. Instruktions-
u
ebene, Anweisungsebene oder Prozedurebene)
• Sollen parallele Programmteile explizit angegeben wer-
den? (explizit oder implizit parallele Programme)
• In welcher Form werden parallele Programmteile ange-
geben? (z.B. als beim Start des Programmes erzeugte
Menge von Prozessen oder etwa Tasks, die dynamisch
erzeugt und zugeordnet werden)
• Wie erfolgt die Abarbeitung der parallelen Programm-
teile im Verh¨ltnis zueinander? (SIMD oder SPMD (Sin-
a
gle Program, Multiple Data); synchrone oder asynchro-
ne Berechnungen)
• Wie findet der Informationsaustausch zwischen paral-
lelen Programmteilen statt? (Kommunikation oder ge-
meinsame Variable)
• Welche Formen der Synchronisation k¨nnen genutzt
o
werden? (z.B. Barrier-Synchronisation oder Sperrme-
chanismen)
Ebenen der Parallelit¨t
a
Unabh¨ngige und damit parallel abarbeitbare Aufgaben
a
k¨nnen auf sehr unterschiedlichen Ebenen eines Programms
o
auftreten, wobei f¨ r die Parallelisierung eines Programmes
u
meist jeweils nur eine Ebene genutzt wird.
• Parallelit¨t auf Instruktionsebene kann ausgenutzt
a
werden, falls zwischen zwei Instruktionen keine Daten-
abh¨ngigkeit besteht. Diese Form der Parallelit¨t kann
a a
durch Compiler auf superskalaren Prozessoren einge-
setzt werden.
39. 2.3 Parallele Programmiermodelle 31
• Bei der Parallelit¨t auf Anweisungsebene werden
a
mehrere Anweisungen auf denselben oder verschiede-
nen Daten parallel ausgef¨ hrt. Eine Form ist die Da-
u
tenparallelit¨t, bei der Datenstrukturen wie Felder in
a
Teilbereiche unterteilt werden, auf denen parallel zuein-
ander dieselben Operationen ausgef¨ hrt werden. Die-
u
se Arbeitsweise wird im SIMD Modell genutzt, in dem
in jedem Schritt die gleiche Anweisung auf evtl. unter-
schiedlichen Daten ausgef¨ hrt wird.
u
• Bei der Parallelit¨t auf Schleifenebene werden un-
a
terschiedliche Iterationen einer Schleifenanweisung par-
allel zueinander ausgef¨ hrt. Besondere Auspr¨gungen
u a
sind die forall und dopar Schleife. Bei der forall-
Schleife werden die Anweisungen im Schleifenrumpf par-
allel in Form von Vektoranweisungen nacheinander ab-
gearbeitet. Die dopar-Schleife f¨ hrt alle Anweisungen
u
einer Schleifeniteration unabh¨ngig vor den anderen
a
Schleifeniterationen aus. Je nach Datenabh¨ngigkeiten
a
zwischen den Schleifeniterationen kann es durch die Par-
allelit¨t auf Schleifenebene zu unterschiedlichen Ergeb-
a
nissen kommen als bei der sequentiellen Abarbeitung
der Schleifenr¨ mpfe. Als parallele Schleife wird eine
u
Schleife bezeichnet, deren Schleifenr¨mpfe keine Daten-
u
abh¨ngigkeit aufweisen und somit eine parallele Abar-
a
beitung zum gleichen Ergebnis f¨ hrt wie die sequentielle
u
Abarbeitung. Parallele Schleifen spielen bei Program-
mierumgebungen wie OpenMP eine wesentliche Rolle.
• Bei der Parallelit¨t auf Funktionsebene werden ge-
a
samte Funktionsaktivierungen eines Programms parallel
zueinander auf verschiedenen Prozessoren oder Prozes-
sorkernen ausgef¨ hrt. Bestehen zwischen parallel aus-
u
zuf¨ hrenden Funktionen Daten- oder Kontrollabh¨ngig-
u a
keiten, so ist eine Koordination zwischen den Funktio-
nen erforderlich. Dies erfolgt in Form von Kommunika-
40. 32 2 Konzepte paralleler Programmierung
tion und Barrier-Anweisungen bei Modellen mit verteil-
tem Adressraum. Ein Beispiel ist die Programmierung
mit MPI (Message Passing Interface) [59, 61]. Bei Mo-
dellen mit gemeinsamem Adressraum ist Synchronisati-
on erforderlich; dies ist also f¨ r die Programmierung von
u
Multicore-Prozessoren notwendig und wird in Kapitel 3
vorgestellt.
Explizite oder implizite Parallelit¨t
a
Eine Voraussetzung f¨ r die parallele Abarbeitung auf ei-
u
nem Multicore-Prozessor ist das Vorhandensein mehrerer
Berechnungsstr¨me. Diese k¨nnen auf recht unterschiedli-
o o
che Art erzeugt werden [60].
Bei impliziter Parallelit¨t braucht der Programmie-
a
rer keine Angaben zur Parallelit¨t zu machen. Zwei unter-
a
schiedliche Vertreter impliziter Parallelit¨t sind paralleli-
a
sierende Compiler oder funktionale Programmiersprachen.
Parallelisierende Compiler erzeugen aus einem gegebenen
sequentiellen Programm ein paralleles Programm und nut-
zen dabei Abh¨ngigkeitsanalysen, um unabh¨ngige Berech-
a a
nungen zu ermitteln. Dies ist in den meisten F¨llen eine
a
komplexe Aufgabe und die Erfolge parallelisierender Com-
piler sind entsprechend begrenzt [55, 66, 5, 2]. Programme
in einer funktionalen Programmiersprache bestehen aus ei-
ner Reihe von Funktionsdefinitionen und einem Ausdruck,
dessen Auswertung das Programmergebnis liefert. Das Po-
tential f¨ r Parallelit¨t liegt in der parallelen Auswertung
u a
der Argumente von Funktionen, da funktionale Program-
me keine Seiteneffekte haben und sich die Argumente somit
nicht beeinflussen k¨nnen [33, 64, 8]. Implizite Parallelit¨t
o a
wird teilweise auch von neuen Sprachen wie Fortress einge-
setzt, vgl. Abschnitt 7.1.
41. 2.3 Parallele Programmiermodelle 33
Explizite Parallelit¨t mit impliziter Zerlegung liegt
a
vor, wenn der Programmierer zwar angibt, wo im Pro-
gramm Potential f¨ r eine parallele Bearbeitung vorliegt,
u
etwa eine parallele Schleife, die explizite Kodierung in Thre-
ads oder Prozesse aber nicht vornehmen muss. Viele paral-
lele FORTRAN-Erweiterungen nutzen dieses Prinzip.
Bei einer expliziten Zerlegung muss der Program-
mierer zus¨tzlich angeben, welche Tasks es f¨ r die parallele
a u
Abarbeitung geben soll, ohne aber eine Zuordnung an Pro-
zesse oder explizite Kommunikation formulieren zu m¨ ssen.
u
Ein Beispiel ist BSP [65]. Die explizite Zuordnung der Tasks
an Prozesse wird in Koordinationssprachen wie Linda [12]
zus¨tzlich angegeben.
a
Bei Programmiermodellen mit expliziter Kommuni-
kation und Synchronisation muss der Programmierer
alle Details der parallelen Abarbeitung angeben. Hierzu
geh¨rt das Message-Passing-Programmiermodell mit MPI,
o
aber auch Programmierumgebungen zur Benutzung von
Threads, wie Pthreads, das in Kap. 4 vorgestellt wird.
Angabe paralleler Programmteile
Sollen vom Programmierer die parallelen Programmteile ex-
plizit angegeben werden, so kann dies in ganz unterschied-
licher Form erfolgen. Bei der Angabe von Teilaufgaben in
Form von Tasks werden diese implizit Prozessoren oder
Kernen zugeordnet. Bei vollkommen explizit paralleler Pro-
grammierung sind die Programmierung von Threads oder
von Prozessen die weit verbreiteten Formen.
Thread-Programmierung: Ein Thread ist eine Fol-
ge von Anweisungen, die parallel zu anderen Anweisungsfol-
gen, also Threads, abgearbeitet werden k¨nnen. Die Thre-
o
ads eines einzelnen Programmes besitzen f¨ r die Abarbei-
u
tung jeweils eigene Ressourcen, wie Programmz¨hler, Sta-
a
42. 34 2 Konzepte paralleler Programmierung
tusinformationen des Prozessors oder einen Stack f¨ r loka-
u
le Daten, nutzen jedoch einen gemeinsamen Datenspeicher.
Damit ist das Thread-Modell f¨ r die Programmierung von
u
Multicore-Prozessoren geeignet.
Message-Passing-Programmierung: Die Message-
Passing-Programmierung nutzt Prozesse, die Programm-
teile bezeichnen, die jeweils auf einem separaten physika-
lischen oder logischen Prozessor abgearbeitet werden und
somit jeweils einen privaten Adressraum besitzen.
Abarbeitung paralleler Programmteile
Die Abarbeitung paralleler Programmteile kann synchron
erfolgen, indem die Anweisungen paralleler Threads oder
Prozesse jeweils gleichzeitig abgearbeitet werden, wie et-
wa im SIMD-Modell, oder asynchron, also unabh¨ngig von-
a
einander bis eine explizite Synchronisation erfolgt, wie et-
wa im SPMD-Modell. Diese Festlegung der Abarbeitung
wird meist vom Programmiermodell der benutzten Pro-
grammierumgebung vorgegeben. Dar¨ ber hinaus gibt es ei-
u
ne Reihe von Programmiermustern, in denen parallele Pro-
grammteile angeordnet werden, z.B. Pipelining, Master-
Worker oder Produzenten-Konsumenten-Modell, und die
vom Softwareentwickler explizit ausgew¨hlt werden.
a
Informationsaustausch
Ein wesentliches Merkmal f¨ r den Informationsaustausch
u
ist die Organisation des Adressraums. Bei einem verteilten
Adressraum werden Daten durch Kommunikation ausge-
tauscht. Dies kann explizit im Programm angegeben sein,
aber auch durch einen Compiler oder das Laufzeitsystem
erzeugt werden. Bei einem gemeinsamen Adressraum kann
43. 2.4 Parallele Leistungsmaße 35
der Informationsaustausch einfach uber gemeinsame Varia-
¨
ble in diesem Adressraum geschehen, auf die lesend oder
schreibend zugegriffen werden kann. Hierdurch kann es je-
doch auch zu Konflikten oder unerw¨ nschten Ergebnis-
u
sen kommen, wenn dies unkoordiniert erfolgt. Die Koor-
dination von parallelen Programmteilen spielt also eine
wichtige Rolle bei der Programmierung eines gemeinsa-
men Adressraums und ist daher ein wesentlicher Bestand-
teil der Thread-Programmierung und der Programmierung
von Multicore-Prozessoren.
Formen der Synchronisation
Synchronisation gibt es in Form von Barrier-Synchronisa-
tion, die bewirkt, dass alle beteiligten Threads oder Pro-
zesse aufeinander warten, und im Sinne der Koordination
von Threads. Letzteres hat insbesondere mit der Vermei-
dung von Konflikten beim Zugriff auf einen gemeinsamen
Adressraum zu tun und setzt Sperrmechanismen und be-
dingtes Warten ein.
2.4 Parallele Leistungsmaße
Ein wesentliches Kriterium zur Bewertung eines parallelen
Programms ist dessen Laufzeit. Die parallele Laufzeit
Tp (n) eines Programmes ist die Zeit zwischen dem Start
der Abarbeitung des parallelen Programmes und der Been-
digung der Abarbeitung aller beteiligten Prozessoren. Die
parallele Laufzeit wird meist in Abh¨ngigkeit von der An-
a
zahl p der zur Ausf¨ hrung benutzten Prozessoren und ei-
u
ner Problemgr¨ße n angegeben, die z.B. durch die Gr¨ße
o o
der Eingabe gegeben ist. F¨ r Multicore-Prozessoren mit ge-
u
meinsamem Adressraum setzt sich die Laufzeit eines paral-
lelen Programmes zusammen aus:
44. 36 2 Konzepte paralleler Programmierung
• der Zeit f¨ r die Durchf¨ hrung von Berechnungen durch
u u
die Prozessorkerne,
• der Zeit f¨ r die Synchronisation beim Zugriff auf ge-
u
meinsame Daten,
• den Wartezeiten, die z.B. wegen ungleicher Verteilung
der Last oder an Synchronisationspunkten entstehen.
Kosten: Die Kosten eines parallelen Programmes, h¨ufig a
auch Arbeit oder Prozessor-Zeit-Produkt genannt, be-
r¨ cksichtigen die Zeit, die alle an der Ausf¨ hrung beteilig-
u u
ten Prozessoren insgesamt zur Abarbeitung des Program-
mes verwenden. Die Kosten Cp (n) eines parallelen Pro-
gramms sind definiert als
Cp (n) = Tp (n) · p
und sind damit ein Maß f¨ r die von allen Prozessoren
u
durchgef¨ hrte Arbeit. Ein paralleles Programm heißt kos-
u
tenoptimal, wenn Cp (n) = T ∗ (n) gilt, d.h. wenn insge-
samt genauso viele Operationen ausgef¨ hrt werden wie vom
u
schnellsten sequentiellen Verfahren, das Laufzeit T ∗ (n) hat.
Speedup: Zur Laufzeitanalyse paralleler Programme
ist insbesondere ein Vergleich mit einer sequentiellen Im-
plementierung von Interesse, um den Nutzen des Einsatzes
der Parallelverarbeitung absch¨tzen zu k¨nnen. F¨ r einen
a o u
solchen Vergleich wird oft der Speedup-Begriff als Maß f¨ r u
den relativen Geschwindigkeitsgewinn herangezogen. Der
Speedup Sp (n) eines parallelen Programmes mit Laufzeit
Tp (n) ist definiert als
T ∗ (n)
Sp (n) = ,
Tp (n)
wobei p die Anzahl der Prozessoren zur L¨sung des Pro-
o
blems der Gr¨ße n bezeichnet. Der Speedup einer paral-
o
lelen Implementierung gibt also den relativen Geschwin-
digkeitsvorteil an, der gegen¨ ber der besten sequentiellen
u
45. 2.4 Parallele Leistungsmaße 37
Implementierung durch den Einsatz von Parallelverarbei-
tung auf p Prozessoren entsteht. Theoretisch gilt immer
Sp (n) ≤ p. Durch Cacheeffekte kann in der Praxis auch
der Fall Sp (n) > p (superlinearer Speedup) auftreten.
Effizienz: Alternativ zum Speedup kann der Begriff der
Effizienz eines parallelen Programmes benutzt werden, der
ein Maß f¨ r den Anteil der Laufzeit ist, den ein Prozessor
u
f¨ r Berechnungen ben¨tigt, die auch im sequentiellen Pro-
u o
gramm vorhanden sind. Die Effizienz Ep (n) eines parallelen
Programms ist definiert als
T ∗ (n) T ∗ (n)
Sp (n)
Ep (n) = = =
Cp (n) p p · Tp (n)
wobei T ∗ (n) die Laufzeit des besten sequentiellen Algorith-
mus und Tp (n) die parallele Laufzeit ist. Liegt kein super-
linearer Speedup vor, gilt Ep (n) ≤ 1. Der ideale Speedup
Sp (n) = p entspricht einer Effizienz Ep (n) = 1.
Amdahlsches Gesetz: Die m¨gliche Verringerung von
o
Laufzeiten durch eine Parallelisierung sind oft begrenzt. So
stellt etwa die Anzahl der Prozessoren die theoretisch obe-
re Schranke des Speedups dar. Weitere Begrenzungen lie-
gen im zu parallelisierenden Algorithmus selber begr¨ ndet,
u
der neben parallelisierbaren Anteilen auch durch Daten-
abh¨ngigkeiten bedingte, inh¨rent sequentielle Anteile ent-
a a
halten kann. Der Effekt von Programmteilen, die sequentiell
ausgef¨ hrt werden m¨ ssen, auf den erreichbaren Speedup
u u
wird durch das Amdahlsche Gesetz quantitativ erfasst
[6]:
Wenn bei einer parallelen Implementierung ein (kon-
stanter) Bruchteil f (0 ≤ f ≤ 1) sequentiell ausgef¨ hrt u
werden muss, setzt sich die Laufzeit der parallelen Imple-
mentierung aus der Laufzeit f · T ∗ (n) des sequentiellen
Teils und der Laufzeit des parallelen Teils, die mindestens
(1 − f )/p · T ∗ (n) betr¨gt, zusammen. F¨ r den erreichbaren
a u
46. 38 2 Konzepte paralleler Programmierung
Speedup gilt damit
T ∗ (n) 1 1
Sp (n) = ≤.
=
∗ (n) + 1−f T ∗ (n) 1−f f
f ·T f+ p
p
Bei dieser Berechnung wird der beste sequentielle Al-
gorithmus verwendet und es wurde angenommen, dass sich
der parallel ausf¨ hrbare Teil perfekt parallelisieren l¨sst.
u a
Durch ein einfaches Beispiel sieht man, dass nicht paral-
lelisierbare Berechnungsteile einen großen Einfluss auf den
erreichbaren Speedup haben: Wenn 20% eines Programmes
sequentiell abgearbeitet werden m¨ ssen, betr¨gt nach Aus-
u a
sage des Amdahlschen Gesetzes der maximal erreichbare
Speedup 5, egal wie viele Prozessoren eingesetzt werden.
Nicht parallelisierbare Teile m¨ ssen insbesondere bei einer
u
großen Anzahl von Prozessoren besonders beachtet werden.
Skalierbarkeit: Das Verhalten der Leistung eines par-
allelen Programmes bei steigender Prozessoranzahl wird
durch die Skalierbarkeit erfasst. Die Skalierbarkeit eines
parallelen Programmes auf einem gegebenen Parallelrech-
ner ist ein Maß f¨ r die Eigenschaft, einen Leistungsgewinn
u
proportional zur Anzahl p der verwendeten Prozessoren
zu erreichen. Der Begriff der Skalierbarkeit wird in unter-
schiedlicher Weise pr¨zisiert, z.B. durch Einbeziehung der
a
Problemgr¨ße n. Eine h¨ufig beobachtete Eigenschaft par-
o a
alleler Algorithmen ist es, dass f¨ r festes n und steigendes
u
p eine S¨ttigung des Speedups eintritt, dass aber f¨ r fes-
a u
tes p und steigende Problemgr¨ße n ein h¨herer Speedup
o o
erzielt wird. In diesem Sinne bedeutet Skalierbarkeit, dass
die Effizienz eines parallelen Programmes bei gleichzeiti-
gem Ansteigen von Prozessoranzahl p und Problemgr¨ße n o
konstant bleibt.
47. 3
Thread-Programmierung
Die Programmierung von Multicore-Prozessoren ist eng mit
der parallelen Programmierung eines gemeinsamen Adress-
raumes und der Thread-Programmierung verbunden. Meh-
rere Berechnungsstr¨me desselben Programms k¨nnen par-
o o
allel zueinander bearbeitet werden und greifen dabei auf
Variablen des gemeinsamen Speichers zu. Diese Berech-
nungsstr¨me werden als Threads bezeichnet. Die Pro-
o
grammierung mit Threads ist ein seit vielen Jahren bekann-
tes Programmierkonzept [9] und kann vom Softwareent-
wickler durch verschiedene Programmierumgebungen oder
-bibliotheken wie Pthreads, Java-Threads, OpenMP oder
Win32 f¨ r Multithreading-Programme genutzt werden.
u
3.1 Threads und Prozesse
Die Abarbeitung von Threads h¨ngt eng mit der Abar-
a
beitung von Prozessen zusammen, so dass beide zun¨chst
a
nochmal genauer definiert und voneinander abgegrenzt wer-
den.
48. 40 3 Thread-Programmierung
Prozesse
Ein Prozess ist ein sich in Ausf¨ hrung befindendes Pro-
u
gramm und umfasst neben dem ausf¨ hrbaren Programmco-
u
de alle Informationen, die zur Ausf¨ hrung des Programms
u
erforderlich sind. Dazu geh¨ren die Daten des Programms
o
auf dem Laufzeitstack oder Heap, die zum Ausf¨ hrungszeit-
u
punkt aktuellen Registerinhalte und der aktuelle Wert des
Programmz¨hlers, der die n¨chste auszuf¨ hrende Instruk-
a a u
tion des Prozesses angibt. Jeder Prozess hat also seinen
eigenen Adressraum. Alle diese Informationen ¨ndern sich
a
w¨hrend der Ausf¨ hrung des Prozesses dynamisch. Wird
a u
die Rechenressource einem anderen Prozess zugeordnet, so
muss der Zustand des suspendierten Prozesses gespeichert
werden, damit die Ausf¨ hrung dieses Prozesses zu einem
u
sp¨teren Zeitpunkt mit genau diesem Zustand fortgesetzt
a
werden kann. Dies wird als Kontextwechsel bezeichnet
und ist je nach Hardwareunterst¨ tzung relativ aufwendig
u
[54]. Prozesse werden bei Multitasking im Zeitscheibenver-
fahren von der Rechenressource abgearbeitet; es handelt
sich also um Nebenl¨ufigkeit und keine Gleichzeitigkeit. Bei
a
Multiprozessor-Systemen ist eine tats¨chliche Parallelit¨t
a a
m¨glich.
o
Beim Erzeugen eines Prozesses muss dieser die zu sei-
ner Ausf¨ hrung erforderlichen Daten erhalten. Im UNIX-
u
Betriebssystem kann ein Prozess P1 mit Hilfe einer fork-
Anweisung einen neuen Prozess P2 erzeugen. Der neue
Kindprozess P2 ist eine identische Kopie des Elternpro-
zesses P1 zum Zeitpunkt des fork-Aufrufes. Dies bedeu-
tet, dass der Kindprozess auf einer Kopie des Adressrau-
mes des Elternprozesses arbeitet und das gleiche Programm
wie der Elternprozess ausf¨ hrt, und zwar ab der der fork-
u
Anweisung folgenden Anweisung. Der Kindprozess hat je-
doch eine eigene Prozessnummer und kann in Abh¨ngigkeit
a
49. 3.1 Threads und Prozesse 41
von dieser Prozessnummer andere Anweisungen als der El-
ternprozess ausf¨ hren, vgl. [46]. Da jeder Prozess einen ei-
u
genen Adressraum hat, ist die Erzeugung und Verwaltung
von Prozessen je nach Gr¨ße des Adressraumes relativ zeit-
o
aufwendig. Weiter kann bei h¨ufiger Kommunikation der
a
Austausch von Daten (¨ ber Sockets) einen nicht unerheb-
u
lichen Anteil der Ausf¨ hrungszeit ausmachen.
u
Threads
Das Threadmodell ist eine Erweiterung des Prozessmodells.
Jeder Prozess besteht anstatt nur aus einem aus mehreren
unabh¨ngigen Berechnungsstr¨men, die w¨hrend der Ab-
a o a
arbeitung des Prozesses durch ein Schedulingverfahren der
Rechenressource zugeteilt werden. Die Berechnungsstr¨me o
eines Prozesses werden als Threads bezeichnet. Das Wort
Thread wurde gew¨hlt, um anzudeuten, dass eine zusam-
a
menh¨ngende, evtl. sehr lange Folge von Instruktionen ab-
a
gearbeitet wird.
Ein wesentliches Merkmal von Threads besteht dar-
in, dass die verschiedenen Threads eines Prozesses sich
den Adressraum des Prozesses teilen, also einen gemein-
samen Adressraum haben. Wenn ein Thread einen Wert im
Adressraum ablegt, kann daher ein anderer Thread des glei-
chen Prozesses diesen unmittelbar darauf lesen. Damit ist
der Informationsaustausch zwischen Threads im Vergleich
zur Kommunikation zwischen Prozessen uber Sockets sehr
¨
schnell. Da die Threads eines Prozesses sich einen Adress-
raum teilen, braucht auch die Erzeugung von Threads we-
sentlich weniger Zeit als die Erzeugung von Prozessen. Das
Kopieren des Adressraumes, das z.B. in UNIX beim Er-
zeugen von Prozessen mit einer fork-Anweisung notwendig
ist, entf¨llt. Das Arbeiten mit mehreren Threads innerhalb
a
eines Prozesses ist somit wesentlich flexibler als das Arbei-
50. 42 3 Thread-Programmierung
ten mit kooperierenden Prozessen, bietet aber die gleichen
Vorteile. Insbesondere ist es m¨glich, die Threads eines Pro-
o
zesses auf verschiedenen Prozessoren oder Prozessorkernen
parallel auszuf¨ hren.
u
Threads k¨nnen auf Benutzerebene als Benutzer-Thre-
o
ads oder auf Betriebssystemebene als Betriebssystem-
Threads implementiert werden. Threads auf Benutzerebe-
ne werden durch eine Thread-Bibliothek ohne Beteiligung
des Betriebssystems verwaltet. Ein Wechsel des ausgef¨ hr-
u
ten Threads kann damit ohne Beteiligung des Betriebssys-
tems erfolgen und ist daher in der Regel wesentlich schneller
als der Wechsel bei Betriebssystem-Threads.
Bibliotheks− BP Betriebssystem−
T
Scheduler Scheduler
T BP
T P
BP
T
P
BP
Prozess 1
P
BP
Bibliotheks−
T
P
BP
Scheduler
T
Prozessoren
BP
T
Prozess n
Betriebssystem−
Prozesse
N:1-Abbildung – Thread-Verwaltung oh-
Abbildung 3.1.
ne Betriebssystem-Threads. Der Scheduler der Thread-Bibliothek
w¨hlt den auszuf¨hrenden Thread T des Benutzerprozesses aus.
a u
Jedem Benutzerprozess ist ein Betriebssystemprozss BP zugeord-
net. Der Betriebssystem-Scheduler w¨hlt die zu einem bestimmten
a
Zeitpunkt auszuf¨hrenden Betriebssystemprozesse aus und bildet
u
diese auf die Prozessoren P ab.
51. 3.1 Threads und Prozesse 43
Der Nachteil von Threads auf Benutzerebene liegt darin,
dass das Betriebssystem keine Kenntnis von den Threads
hat und nur gesamte Prozesse verwaltet. Wenn ein Thread
eines Prozesses das Betriebssystem aufruft, um z.B. eine
I/O-Operation durchzuf¨ hren, wird der CPU-Scheduler des
u
Betriebssystems den gesamten Prozess suspendieren und
die Rechenressource einem anderen Prozess zuteilen, da das
Betriebssystem nicht weiß, dass innerhalb des Prozesses zu
einem anderen Thread umgeschaltet werden kann. Dies gilt
f¨ r Betriebssystem-Threads nicht, da das Betriebssystem
u
die Threads direkt verwaltet.
BT Betriebssystem−
T
Scheduler
T BT
T P
BT
T
P
BT
Prozess 1
P
BT
P
T BT
T BT Prozessoren
T
Betriebssystem−
Prozess n
Threads
Abbildung 3.2. 1:1-Abbildung – Thread-Verwaltung mit
Betriebssystem-Threads. Jeder Benutzer-Thread T wird eindeutig
einem Betriebssystem-Thread BT zugeordnet.
52. 44 3 Thread-Programmierung
Bibliotheks− BT Betriebssystem−
T
Scheduler Scheduler
T BT
T P
BT
T
P
BT
Prozess 1
P
BT
P
T BT
T
Prozessoren
BT
T Bibliotheks−
Scheduler
Prozess n Betriebssystem−
Threads
Abbildung 3.3. N:M-Abbildung – Thread-Verwaltung mit
Betriebssystem-Threads und zweistufigem Scheduling. Benutzer-
Threads T verschiedener Prozesse werden einer Menge von
Betriebssystem-Threads BT zugeordnet (N:M-Abbildung).
Ausf¨hrungsmodelle f¨r Threads
u u
Wird eine Thread-Verwaltung durch das Betriebssystem
nicht unterst¨ tzt, so ist die Thread-Bibliothek f¨ r das Sche-
u u
duling der Threads verantwortlich. Alle Benutzer-Threads
eines Prozesses werden vom Bibliotheks-Scheduler auf einen
Betriebssystem-Prozess abgebildet, was N:1-Abbildung
genannt wird, siehe Abb. 3.1. Stellt das Betriebssystem eine
Thread-Verwaltung zur Verf¨ gung, so gibt es f¨ r die Ab-
u u
bildung von Benutzer-Threads auf Betriebssystem-Threads
zwei M¨glichkeiten: Die erste ist die 1:1-Abbildung, die
o
f¨ r jeden Benutzer-Thread einen Betriebssystem-Thread
u
erzeugt, siehe Abb. 3.2. Der Betriebssystem-Scheduler w¨hlta
den jeweils auszuf¨ hrenden Betriebssystem-Thread aus und
u
verwaltet bei Mehr-Prozessor-Systemen die Ausf¨ hrung der
u
Betriebssystem-Threads auf den verschiedenen Prozesso-