OpenMP. Michael Westermann

Größe: px
Ab Seite anzeigen:

Download "OpenMP. Michael Westermann"

Transkript

1 Westfälische Wilhelms-Universität Münster Ausarbeitung OpenMP im Rahmen des Seminars Parallele und verteilte Programmierung Michael Westermann Themensteller: Prof. Dr. Herbert Kuchen Betreuer: Dipl. Wirt.-Inform. Philipp Ciechanowicz Institut für Wirtschaftsinformatik Praktische Informatik in der Wirtschaft

2 Inhaltsverzeichnis 1 Einleitung 1 2 Grundlagen Das OpenMP-Programmiermodell Modell des gemeinsamen Speichers Vergleich von OpenMP und MPI OpenMP-Direktiven Variablendeklarationen Direktiven zur Parallelisierung von Programmbereichen parallel-direktive als Basis für parallele Bereiche for-direktive zur Parallelisierung von Schleifen sections-direktive zur Parallelisierung von Abschnitten Anzahl Threads Koordination und Synchronisation von Threads Kritische Abschnitte Atomare Operationen Synchronisation Ausführung ausschließlich durch den Master-Thread Zusammenfassung und Ausblick 21 A Programm-Beispiele 22 A.1 Ausgabe Threadnummern A.2 Primzahlen-Ausgabe, seriell A.3 Primzahlen-Ausgabe, parallel A.4 Primzahlen-Ausgabe, parallel und geordnet B Tabelle der Ausführungszeiten 26 Literaturverzeichnis 27 i

3 Kapitel 1: Einleitung 1 Einleitung Multiprozessor-Desktoprechner oder Rechner mit Multicore-Prozessoren, die im weiteren Verlauf dieser Arbeit einheitlich als Multiprozessor-System bezeichnet werden, werden immer kostengünstiger und häufiger eingesetzt. Solche Systeme stellen parallele Rechenleistung bereit, so dass sie mehrere Threads gleichzeitig bearbeiten können. Um derartige parallele Rechenleistung effizient ausnutzen und somit die Ausführungszeit eines Programms senken zu können, sind jedoch parallele Programmiertechniken erforderlich. Auf Systemen mit gemeinsamem Speicher bietet sich hierfür die Anwendung von OpenMP an. OpenMP, das für Open specifications for Multi Processing steht, ist eine Spezifikation für parallele Programmierung auf Multiprozessor-Systemen mit gemeinsa- mem Speicher. Seit 1997 gemeinschaftlich von verschiedenen Hard- und Softwareherstellern entwickelt, ist es schnell zum Standard für die Parallelisierung von Anwendungen auf Systemen mit gemeinsamem Speicher geworden [Ch01, S. xiii]. OpenMP hält Compiler-Direktiven, Bibliotheksfunktionen und Umgebungsvariablen bereit und stellt Bindings für die Programmiersprachen C, C++ und Fortran zur Verfügung [Qu04, Kap. 17.1]. Diese Sprachen werden um Konstrukte zur Ausführung eines Programms mit unterschiedlichen Daten durch mehrere Threads, zur Aufteilung von Arbeit auf mehrere Threads, zur Synchronisation von Threads und zur Deklaration von gemeinsamen und privaten Variablen der Threads erweitert [RR07, S. 355]. Einzelne Bereiche eines seriellen Programms können durch das Einfügen weniger Direktiven parallelisiert werden (inkrementelles Parallelisieren). Somit ist ein gleichzeitiges Abarbeiten auf mehreren Prozessoren möglich, wodurch die Ausführungszeit erheblich gesenkt werden kann. Die Spezifikationen von OpenMP sind in [Op05] zu finden. Im Rahmen dieser Seminararbeit wird der Fokus auf C und C++ gelegt, das Binding zu Fortran wird nicht weiter betrachtet. In dieser Arbeit werden zunächst in Kapitel 2 das Programmiermodell von Open- MP und das Modell des gemeinsamen Speichers, auf dem OpenMP beruht, erläutert und eine Abgrenzung von OpenMP gegenüber dem Message-Passing-Interfaces (MPI) vorgenommen. In Kapitel 3 werden die wichtigsten Direktiven von OpenMP erläutert. Zunächst wird in Abschnitt 3.1 auf die Variablendeklarationen eingegangen, die beispielsweise festlegen, ob eine Variable für alle Threads gemeinsam ist oder für jeden Thread neu angelegt wird. Im folgenden Abschnitt 3.2, der den Hauptteil dieser Arbeit darstellt, werden die verschiedenen Direktiven zur Parallelisierung eines Programmabschnitts vorgestellt, bevor in Abschnitt 3.3 darauf eingangen wird, wie die Anzahl Threads festgelegt wird. Dem folgen im Abschnitt 3.4 Direktiven, mit denen 1

4 Kapitel 2: Grundlagen Threads koordiniert und synchronisiert werden können. Zum Abschluss wird in Kapitel 4 die Arbeit zusammengefasst und auf die zukünftige Bedeutung von OpenMP eingegangen. 2 Grundlagen Im Folgenden wird zunächst das auf parallel arbeitende Threads basierende Programmiermodell von OpenMP vorgestellt, das auch als Fork-join-Prinzip bezeichnet wird. Anschließend wird auf das Modell des gemeinsamen Speichers eingegangen, auf dem OpenMP basiert. Im letzten Abschnitt des Grundlagen-Kapitels wird kurz in das Message-Passing-Interface (MPI) eingeführt, bevor auf dessen Unterschiede zu OpenMP näher eingegangen wird. 2.1 Das OpenMP-Programmiermodell Grundlage von OpenMP ist die nebenläufige Abarbeitung von parallelen Bereichen durch parallel arbeitende Threads, die nach einem Fork-join-Prinzip erzeugt und beendet werden [RR07, S. 355]. Hierbei wird das Programm zunächst von nur einem einzigen Thread alleine und sequentiell ausgeführt. Erreicht der Thread bei der Ausführung des Codes einen Programmabschnitt, der mittels OpenMP parallelisiert werden soll, erzeugt der Thread ein Team von Threads, dem er selber als Master-Thread und eine bestimmte Anzahl weiterer Threads angehören. Dieser Vorgang wird als fork bezeichnet, da der Master-Thread zu mehreren Threads aufgegabelt wird. Der parallele Bereich wird von dem gesamten Team von Threads einschließlich des Master-Threads nebenläufig ausgeführt. Hierbei kann die Arbeit explizit auf die einzelnen Threads verteilt werden oder alle Threads des Teams führen den gleichen Programmcode aus. Auf die Varianten der Ausführung wird in Abschnitt 3.2 näher eingegangen. In OpenMP ist es möglich, parallele Bereiche zu verschachteln, also innerhalb eines parallelen Bereiches einen weiteren parallelen Bereich zu starten. Der Thread, der auf den inneren parallelen Bereich trifft, wird zum Master-Thread dieses inneren Bereiches. Liegt keine Verschachtelung von parallelen Bereichen vor, so bleibt die Anzahl der Threads konstant. Am Ende eines parallelen Bereiches werden die dem Team zugehörigen Threads synchronisiert und mit Ausnahme des Master-Threads alle beendet. Nach diesem Vorgang, der als join bezeichnet wird, setzt der Master- Thread die Ausführung alleine und sequentiell fort. Das Fork-join-Prinzip ist in Abb. 1 dargestellt. 2

5 Kapitel 2: Grundlagen Abbildung 1: Das Fork-join-Prinzip Quelle: In Anlehnung an [Qu04, Figure 17.2] 2.2 Modell des gemeinsamen Speichers OpenMP wurde für die parallele Programmierung auf Multiprozessor-Systemen mit gemeinsamem Speicher entwickelt. Auf einem solchen System teilen sich zwei oder mehr Prozessoren einen unbeschränkten Zugriff auf einen gemeinsamen Arbeitsspeicher. Somit sehen die Threads eines Prozesses den gleichen Adressraum, unabhängig davon, von welchem Prozessor sie bearbeitet werden [Ta03, S. 541]. Eine typische Architektur mit gemeinsamem Speicher ist in Abb. 2 dargestellt. Abbildung 2: Architektur mit gemeinsamem Speicher Quelle: In Anlehnung an [Ta03, S. 540] Der verteilte gemeinsame Speicher (distributed shared memory, DSM) wird ebenfalls von OpenMP unterstützt. Er ist vergleichbar mit einem virtuellen Speichersystem, bei dem sich die Speicherseiten auf physikalisch entfernten Computern befinden. Ein solches System ist dann sinnvoll, wenn die Anzahl an Prozessoren so groß wird, dass die Bandbreite des gemeinsamen Speichers zum Engpass wird. Im weiteren Verlauf dieser Arbeit wird keine Unterscheidung zwischen gemeinsamem Speicher und verteiltem gemeinsamen Speicher gemacht und beides einheitlich als gemeinsamer Speicher bezeichnet. 3

6 Kapitel 2: Grundlagen 2.3 Vergleich von OpenMP und MPI Neben OpenMP gibt es noch weitere Spezifikationen für parallele Programmierung. Auf Computersystemen mit verteiltem nicht-gemeinsamen Speicher wird häufig das Message-Passing-Interface (MPI) eingesetzt. Dieses stellt einen Standard für den Nachrichtenaustausch zwischen parallel zueinander arbeitenden Prozessen auf verteilten Systemen bereit. Jeder Prozess hat hierbei seine eigenen lokalen Daten und kann sich durch das explizite Verschicken von Nachrichten mit anderen Prozessen austauschen [RR07, S. 207]. MPI und OpenMP haben beide Vor- und Nachteile, so dass situationsbedingt zu entscheiden ist, welches Verfahren sinnvoller einzusetzen ist. Im Folgenden werden MPI und OpenMP anhand einiger Kriterien verglichen: OpenMP ist auf Systeme mit gemeinsamem Speicher begrenzt, während MPI bevorzugt auf Systeme mit verteiltem Speicher angewendet wird, aber auch auf Systeme mit gemeinsamem Speicher einsetzbar ist. Ein OpenMP-Programm wird von einem Prozess mit mindestens einem Thread ausgeführt. Ein MPI-Programm hingegen besteht in der Regel aus mehreren Prozessen, die Nachrichten austauschen können. Die Anzahl der Prozesse entspricht bei MPI in der Regel der Anzahl der Prozessoren des verteilten Computersystems, bei OpenMP richtet sich in der Regel die Anzahl der Threads nach der Anzahl der Prozessoren. Die Kommunikation findet bei MPI mittels Message Passing statt, bei OpenMP hingegen geschieht dies über gemeinsame Variablen der Threads. Bei den unterstützten Programmiersprachen hingegen gibt es keine Unterschiede zwischen OpenMP und MPI, beide stellen Bindings für C, C++ und Fortran bereit. Besteht bereits eine serielle Version eines Programms, so kann dieses durch das Einfügen von OpenMP-Direktiven mit relativ geringem Aufwand parallelisiert werden (inkrementelle Parallelisierung). Im Vergleich hierzu ist die Parallelisierung eines Programms mittels MPI mit erheblichem Aufwand verbunden. Ein weiterer Vorteil von OpenMP ist, dass der Quellcode nicht geändert werden muss, wenn das Programm auf einem System ausgeführt wird, das OpenMP nicht unterstützt. In diesem Fall ignoriert der Compiler die OpenMP-Direktiven und führt das Programm seriell aus. Ein Vorteil von MPI hingegen ist, dass es auf sehr hohe Anzahl von Prozessoren skalierbar ist. MPI und OpenMP können auch kombiniert eingesetzt werden, indem auf einzelnen Multiprozessor-Systemen mit gemeinsamen Speicher OpenMP-Programme laufen, die sich mittels MPI austauschen. 4

7 3 OpenMP-Direktiven Mit OpenMP können Abschnitte eines Programms parallel von mehreren Threads ausgeführt werden. Die Steuerung der parallelen Abarbeitung von Programmabschnitten wird mittels Compiler-Direktiven umgesetzt. Damit das Programm die OpenMP-Direktiven übersetzen kann, ist zunächst die Datei omp.h durch den Befehl include <omp.h> in das Programm einzubinden. Compiler-Direktiven für OpenMP haben in C und C++ folgende Syntax: #pragma omp <Klausel> Unterstützt der entsprechende Compiler kein OpenMP, so wird diese Zeile ignoriert und das Programm wird mit nur einem Thread seriell ausgeführt. Dem Entwickler wird es somit einfach gemacht, da er den Quelltext eines parallelen Programms nicht modifizieren muss, falls es von einem Compiler ausgeführt werden soll, der OpenMP nicht unterstützt oder bei dem OpenMP deaktiviert ist. OpenMP unterstützt zwei generelle Arten von Parallelisierung: Zum einen ist es möglich, eine Gruppe von Threads zu erzeugen, die alle den gleichen Programmabschnitt nebenläufig zueinander ausführen. Zum anderen stellt OpenMP Direktiven bereit, um die Arbeit auf mehrere Threads zu verteilen. In beiden Fällen wird zu Beginn des parallelen Bereiches die Klausel parallel verwendet, die im Abschnitt näher erläutert wird. Folgt keine weitere Direktive, führen alle Threads den gleichen Programmcode aus. Sollen die Iterationen einer for-schleife auf mehrere Threads verteilt werden, wird innerhalb des parallelen Bereichs die for-direktive eingesetzt, worauf im Abschnitt näher eingegangen wird. Neben der Parallelisierung einer Schleife besteht auch die Möglichkeit, dass jeder Thread einen anderen Abschnitt eines Programms nebenläufig zu den anderen Threads ausführt. Dieses wird mit der sections-direktive umgesetzt, die im Abschnitt ausführlich erklärt wird. 3.1 Variablendeklarationen In einem parallelen OpenMP-Programm benutzen mehrere Threads einen gemeinsamen Speicher. Auf diese Weise können alle Threads auf die gleichen gemeinsamen Variablen zugreifen, wodurch ein Austausch zwischen den Threads ermöglicht wird, indem ein Thread der Variable einen Wert zuweist und ein anderer Thread diesen Wert ausliest. Variablen können auch als private Variablen deklariert werden. In diesem Fall wird für jeden Thread eine eigene Instanz der Variable im Thread-eigenen Speicher angelegt, die alle vom gleichen Typ und der gleichen Größe sein müssen. Diese privaten Variablen können für jeden Thread einen anderen Wert annehmen 5

8 und nur der zugehörige Thread kann auf diese zugreifen. Ob eine Variable als gemeinsame oder als private Variable deklariert wird, hängt nicht nur davon ab, ob die Threads über diese Variable miteinander kommunizieren, sondern insbesondere auch vom Aufbau des parallelen Bereichs. Wird beispielsweise eine Variable als Indexvariable einer parallel ausgeführten Schleife eingesetzt, so muss diese Indexvariable privat sein, da sie in jedem Thread einen anderen Wert annimmt. Diese Entscheidung muss sorgfältig getroffen werden, da eine falsche Deklaration von Variablen zu den häufigsten Fehlern in parallelen Programmen mit gemeinsamem Speicher gehört [Ch01, S. 48]. Ob eine Variable in einem parallelen Bereich für alle Threads gemeinsam oder privat ist, wird zu Beginn des parallelen Bereiches festgelegt. Dieses wird mittels Parametern, die der entsprechenden Direktive übergeben werden, realisiert. Bei Angabe des Parameters shared(liste der Variablen ) werden die in der Liste enthaltenen Variablen als gemeinsame Variablen deklariert, so dass eine Referenz auf diese Variable in verschiedenen Threads auf die gleiche Instanz im gemeinsamen Speicher verweist. So wird auch eine Änderung der Variable auf der globalen Instanz im gemeinsamen Speicher ausgeführt, sodass der neue Wert für alle Threads verfügbar ist. Wenn für jeden Thread eine eigene Instanz einer Variable erzeugt werden soll, so wird der Direktive der Parameter private(liste der Variablen ) übergeben, wobei Liste der Variablen alle Variablen enthält, für die dies gelten soll. Auch wenn vor Erreichen des parallelen Bereichs womöglich eine gleichnamige Variable existiert hat, sind die privaten Variablen, im Gegensatz zu den gemeinsamen Variablen, zu Beginn des parallelen Bereiches nicht initialisiert und ihre Werte somit undefiniert. Von der fehlenden Initialisierung zu Beginn des parallelen Bereichs gibt es allerdings Ausnahmen: Zum Einen ist die Indexvariable einer parallelisierten for-schleife bereits initialisiert. In jedem Thread hat die Indexvariable zu Beginn einen anderen Wert, je nachdem welche Iteration dieser Thread ausführt (siehe Abschnitt 3.2.2). Zum Anderen werden in C++ private Variablen, die vom Typ einer Klasse oder Struktur sind und einen Konstruktor haben, beim Anlegen für die einzelnen Threads initialisiert, indem der Konstruktor aufgerufen wird. Ist hingegen explizit erwünscht, dass die privaten Variablen mit dem Wert initialisiert werden, den die Variablen beim Erreichen des parallelen Bereich hatten, so wird statt des private-parameters der Parameter firstprivate(liste der Variablen ) verwendet, in dessen Liste die Variablen einzutragen sind, für die eine derartige Initialisierung vorgenommen werden soll. Eine Variable, die während eines parallelen Bereichs als private Variable deklariert war, ist nach Beenden dieses Abschnitts undefiniert, um Konsistenz zwi- 6

9 schen serieller und paralleler Ausführung des Abschnitts zu erreichen. Allerdings ist es auch in diesem Fall möglich, dass eine im parallelen Bereich als privat deklarierte Variable nach Beenden dieses Bereichs ihren Wert behält. Dafür wird anstatt des private-parameters der Parameter lastprivate(liste der Variablen ) verwendet. Des Weiteren besteht die Möglichkeit, eine Variable als Reduktionsvariable zu deklarieren. In diesem Fall erhält jeder Thread zunächst eine private Kopie der Variable. Am Ende des Abschnitts, zu der die Direktive gehört, wird die ursprüngliche Variable mit den Kopien der entsprechenden Variablen aller Threads entsprechend der Reduktionsoperation verknüpft. Ist der Operator beispielsweise +, so werden alle Werte der Kopien auf den ursprünglichen Wert hinzu addiert und das Ergebnis dieser Addition der ursprünglichen Variable als Wert zugewiesen. Um Variablen als Reduktionsvariablen zu deklarieren, ist der Direktive der Parameter reduction(op : Liste der Variablen ) zu übergeben, wobei op {+,,, &,ˆ,, &&,. Die privaten Kopien der Variablen werden mit dem neutralen Element des angegebenen Operators initialisiert. Für die Operatoren +,, &,,ˆ und ist das neutrale Element der Wert 0, für die Operatoren und && der Wert 1. [Op05, S. 79f.] Neben den beschriebenen Varianten der Variablendeklaration besteht noch die Möglichkeit, Variablen als threadprivate oder copyin zu deklarieren, worauf in dieser Arbeit nicht näher eingegangen wird. Jeder Variable darf, mit Ausnahme einer gleichzeitigen Zuweisung von firstprivate und lastprivate, nur eine Variablen-Deklaration zugewiesen werden. Des Weiteren ist zu beachten, dass einzelnen Elementen eines Arrays oder einer Struktur keine Deklaration zugewiesen werden kann, sondern nur dem kompletten Konstrukt. Wird eine Variable in keiner der Deklarationen erwähnt, wird sie standardmäßig als gemeinsame Variable deklariert. Eine Ausnahme hiervon bildet die bei der Aufteilung einer Schleife auf mehrere Threads erzeugte Index-Variable der Schleife, die standardmäßig als private Variable deklariert wird. Soll ein explizites Deklarieren jeder im parallelen Bereich verwendeten Variable erzwungen werden, so wird der Direktive zusätzlich der Parameter default(none) hinzugefügt. 3.2 Direktiven zur Parallelisierung von Programmbereichen In diesem Abschnitt werden die Direktiven, mit denen einzelne Bereiche eines Programms parallelisiert werden können, erläutert. Zunächst wird auf die parallel- Direktive eingegangen, bei deren Aufruf Threads erzeugt werden, die den darauf folgenden Anweisungsblock parallel ausführen. Sie ist Grundlage für die anschließend 7

10 erklärten Direktiven, die die Arbeit auf mehrere Threads verteilen. Die for-direktive verteilt die Iterationen einer Schleife auf mehrere Threads (siehe Abschnitt 3.2.2), mit der sections-direktive können unabhängige Abschnitte von je einem Thread parallel zueinander ausgeführt werden (siehe Abschnitt 3.2.3) parallel-direktive als Basis für parallele Bereiche Mit Hilfe der parallel-direktive wird ein Abschnitt eines Programms von mehreren Threads gleichzeitig ausgeführt. Folgt keine Direktive, die die Arbeit auf mehrere Threads verteilt, führen alle Threads den gleichen Programmtext in replizierter Art aus. Dieses wird auch als SPMD (single-program multiple-data) bezeichnet [RR07, S. 356] Syntax Die generelle Syntax des parallel-konstruktes sieht folgendermaßen aus: #pragma omp parallel [Parameter [Parameter]...] { Anweisungsblock Welche Ausdrücke als Parameter für die parallel-direktive einsetzbar sind, ist in Tabelle 1 abzulesen. Direktive shared(liste der Variablen) private(liste der Variablen) firstprivate(liste der Variablen) lastprivate(liste der Variablen) default(shared / none) copyin(liste der Variablen) reduction(operetor: Liste der Variablen) if(skalarer Ausdruck) ordered schedule(typ [, Blockgröße]) nowait num threads(positiver Integer-Ausdruck) parallel X X X X X X X X for X X X X X X X sections X X X X X Tabelle 1: Zuordnung der jeweils zulässigen Parameter zu den einzelnen Direktiven 8

11 Beschreibung Bei Erreichen der parallel-direktive werden nach dem in Abschnitt 2.1 vorgestelltem Fork-join-Prinzip eine bestimmte Anzahl Threads erzeugt. Auf die Ermittlung der Anzahl der Threads, unter anderem mit Hilfe des Parameters num threads, wird in Abschnitt 3.3 näher eingegangen. Jedem Thread wird vom System eine eindeutige Thread-Nummer zugewiesen, wobei der Master-Thread immer die Thread- Nummer 0 und die anderen Threads bei eins beginnend aufsteigend durchnummeriert werden. Die Thread-Nummer des aktuellen Threads kann ermittelt werden, indem der Thread die Funktion omp get thread num() aufruft. Die Parameter shared, private, firstprivate, default, reduction und copyin legen fest, ob die einzelnen Variablen für jeden Thread privat oder für alle Threads gemeinsam sind (siehe Abschnitt 3.1). Bei Angabe des if-parameters wird zunächst der skalare Ausdruck ausgewertet. Ergibt sich für den Ausdruck ein Wert ungleich Null oder ist kein if-parameter angegeben, so wird der auf die Direktive folgende Anweisungsblock parallel ausgeführt, andernfalls wird die Direktive nicht weiter betrachtet und der Anweisungsblock wird von nur einem Thread seriell ausgeführt. Sind die Threads erstellt, führt jeder Thread für sich den direkt auf die Direktive folgenden Anweisungsblock aus. Ist der Anweisungsblock dabei nicht von geschweiften Klammern umrundet, so gilt ausschließlich der direkt auf die parallel-direktive folgende Befehl als Anweisungsblock Restriktionen Eine Bedingung an den Anweisungsblock ist, dass alle Threads den ersten und letzten Befehl des Blockes durchlaufen. Es darf demnach innerhalb eines Blockes keinen Sprung geben, der den Block verlässt. Somit ist beispielsweise keine return- Anweisung innerhalb eines Blockes erlaubt. Sprünge, die innerhalb des Blockes verbleiben, sind hingegen erlaubt. Der Anweisungsblock darf ebenso nicht innerhalb eines in dem Block begonnen Konstruktes enden, wie zum Beispiel vor dem Ende eines in dem Block beginnenden if-konstruktes. Des Weiteren ist zu beachten, dass die optionalen Parameter if und num threads nicht mehrfach in der Direktive stehen dürfen. Wird innerhalb des parallelen Bereichs eine Exception geworfen (throw-klausel), so ist sicherzustellen, dass diese Exception innerhalb des parallelen Bereichs und von dem Thread, der die Exception geworfen hat, abgefangen wird [Op05, S. 28] Beispiel Anhand eines Beispiels, das im Anhang unter A.1 zu finden ist, wird der Ablauf näher erläutert: Zunächst wird die Datei omp.h in das Programm eingebun- 9

12 den. Anschließend wird die Integer-Variable nummer deklariert. Im Hauptteil des Programms wird die parallel-direktive benutzt. Der Parameter num threads(4) veranlasst, dass neben dem aktuellen Thread drei weitere Threads erzeugt werden, der parallele Bereich also von insgesamt vier Threads bearbeitet wird (siehe Abschnitt 3.3). Da die Variable nummer als private Variable definiert ist, besitzt jeder Thread eine eigene Instanz dieser Variable. Diese Threads werden im folgenden parallel zueinander ausgeführt. Zunächst wird der Variable nummer die Nummer des aktuellen Threads zugewiesen. Im nächsten Schritt wird diese Nummer ausgegeben. Eine mögliche Ausgabe ist unter dem Quellcode, der im Anhang unter A.1 zu finden ist, abgedruckt. Hierbei kann keine Aussage darüber getroffen werden, in welcher Reihenfolge die verschiedenen Threads diesen Befehl ausführen. Am Ende des Anweisungsblocks werden die Threads synchronisiert, d.h. das Programm wird erst fortgesetzt, wenn alle Threads das Ende des Anweisungsblocks erreicht haben. Sobald dieses der Fall ist, werden alle Threads außer des Master-Threads beendet. Dieser setzt die Programmausführung seriell fort for-direktive zur Parallelisierung von Schleifen Bei der Parallelisierung einer for-schleife mittels OpenMP werden die einzelnen Iterationen der Schleifenausführung auf mehrere Threads verteilt, die durch mehrere Prozessoren parallel abgearbeitet werden können. Voraussetzung hierfür ist, dass die Anzahl der Iterationen bereits vor dem Ausführen berechenbar sein muss. Außerdem darf kein Schleifendurchlauf ein Ergebnis eines anderes Durchlaufs verwenden, so dass die einzelnen Iterationen der Schleife unabhängig voneinander ausgeführt werden können. Des Weiteren darf die Ausführung des Programms nicht davon abhängen, welcher Thread welchen Schleifendurchlauf bearbeitet. Eine weitere Voraussetzung ist, dass die Abarbeitung der Schleife nicht durch eine break-anweisung abgebrochen werden darf. Durch die Verteilung der Iterationen auf mehrere Threads ist es auf Multiprozessorsystemen möglich, die Laufzeit der Schleife zu reduzieren. Die Parallelisierung von Schleifen gehört zu den bedeutendsten und am häufigsten angewendeten OpenMP-Direktiven [Ch01, S. 41 f.] Syntax Die Syntax zur Parallelisierung einer Schleife innerhalb eines parallelen Bereichs ist folgendermaßen aufgebaut: 10

13 #pragma omp for [Parameter [Parameter]...] for (Index = Startwert ; Test ; Inkrementierung ) { Schleifenrumpf Welche Parameter hier eingesetzt werden dürfen ist in Tabelle 1 abzulesen. Die for-schleife muss in folgender Form vorliegen, damit bereits vor Ausführung der Schleife die Anzahl der Durchläufe berechnet werden kann: Die Indexvariable muss vom Typ int sein. Ihr wird bei der Initialisierung der Schleife ein Startwert zugewiesen, der auch als schleifenunabhängiger Integer-Ausdruck vorliegen darf. Der Test-Ausdruck im Kopf der for-schleife, dessen Ergebnis wahr ist, wenn die Schleife ein weiteres Mal ausgeführt werden soll, vergleicht die Indexvariable mit einem Integer-Ausdruck, dessen Wert sich während der Schleifenausführung nicht verändern darf. Als Operatoren sind hier <, <=, > und >= erlaubt. Der Inkrementierungs-Ausdruck muss die Indexvariable nach jedem Schleifendurchlauf um einen gleichen Wert erhöhen oder erniedrigen. Wenn der Vergleichsoperator < oder <= ist, dann muss der Wert erhöht werden, ansonsten erniedrigt. Hier sind folgende Ausdrücke erlaubt, wobei i für die Indexvariable und incr für einen schleifenunabhängigen Integer-Ausdruck steht: ++i, i++, --i, i--, i+=incr, i-=incr, i=i+incr, i=incr+i, i=i-incr. Besteht der parallele Bereich ausschließlich aus einer zu parallelisierenden Schleife, so ist es möglich, die Direktiven zu Beginn des parallelen Bereichs und zur Parallelisierung der Schleife zu kombinieren: #pragma omp parallel for [Parameter [Parameter]...] for (Index = Startwert; Test ; Inkrementierung ) { Schleifenrumpf Mit Ausnahme des nowait-parameters, der nicht mehr zulässig ist und auf den später näher eingegangen wird, kann bei der Kombination der beiden Direktiven jeder Parameter verwendet werden, der bei mindestens einer der beiden Direktiven zulässig ist Beschreibung In diesem Teilabschnitt werden die Parameter der for-direktive näher erläutert. Der schedule-parameter Wie die einzelnen Schleifendurchläufe auf die Threads des Teams verteilt werden, wird mit dem schedule-parameter festgelegt. Diesem werden der Typ, nach dem die 11

14 Aufteilung der Schleifeniterationen erfolgen soll, und optional eine Blockgröße als Parameter übergeben. Wird eine Blockgröße übergeben, so muss dieses ein Integer- Ausdruck sein, dessen Wert positiv ist und während der Schleifenausführung nicht verändert werden darf. Folgende Typen der Verteilung werden unterstützt: schedule(static, Blockgröße ): Die Schleifeniterationen werden statisch auf die Threads verteilt. Die Iterationen werden in Blöcke der festen Größe Blockgröße aufgeteilt und nach aufsteigender Thread-Nummer nach der Round- Robin-Strategie auf die Threads verteilt. Der letzte Block kann hierbei kleiner sein als die vorherigen. Ist keine Blockgröße angegeben, wird sie so gesetzt, dass jeder Thread einen etwa gleich großen Block aufeinander folgender Iterationen zugeteilt bekommt. Bei statischer Verteilung steht also bereits vor Ausführung fest, welcher Thread welche Iterationen ausführen wird. schedule(dynamic, Blockgröße ): Bei dieser Variante werden die Iterationen dynamisch auf die Threads verteilt. Jedem Thread werden zunächst so viele Iterationen zugewiesen, dass ihre Anzahl der Blockgröße entspricht. Sobald ein Thread diese abgearbeitet hat, bekommt er einen neuen Block der Größe Blockgröße zugewiesen, bis alle Iterationen verteilt sind. Auch hier kann der letzte Block kleiner sein als die vorherigen. Ist keine Blockgröße angegeben, wird als Defaultwert 1 verwendet. In diesem Fall wird jede Iteration einzeln einem Thread zugeteilt. Benötigt ein Thread durchschnittlich pro Block weniger Zeit zur Abarbeitung seiner Blöcke als andere Threads (z.b. schnellerer Prozessor oder weniger rechenintensive Iterationen), führt dies bei dynamischer Verteilung dazu, dass er über die gesamte Abarbeitungszeit insgesamt mehr Blöcke zugewiesen bekommt als andere Threads. Es findet also eine bessere Lastverteilung auf die einzelnen Prozessoren statt als bei der statischen Verteilung. schedule(guided, Blockgröße ): Hier werden die Iterationen ebenfalls dynamisch auf die Threads verteilt. Sei a die Anzahl der noch nicht bearbeiteten Iterationen, n die Anzahl der Threads und k die Blockgröße. Dann werden dem nächsten Thread max(k, a ) Iterationen zugewiesen. Eine Ausnahme ist auch n hier der letzte Block, der erreicht ist wenn a < k ist und eine Größe von a hat. Die Anzahl zugeteilter Iterationen nimmt also stetig ab. Ist keine Blockgröße angegeben, wird sie auf 1 gesetzt. Auch hier findet eine Lastverteilung auf die einzelnen Prozessoren statt. Im Vergleich zur dynamischen Verteilung werden die Iterationen auf insgesamt weniger Blöcke verteilt, dafür ist die Berechnung der verschiedenen Größen der Blöcke aufwendiger. 12

15 schedule(runtime): Bei dieser Angabe wird das Verfahren zur Verteilung der Iterationen auf die Threads erst zur Laufzeit des Programms bestimmt. Das geschieht mit Hilfe der Umgebungsvariable run-sched-var. Wird diese Variable beispielsweise vor dem Start des Programms durch die Eingabe von setenv OMP_SCHEDULE "static, 2" gesetzt, so wird ein statisches Scheduling mit einer Blockgröße von 2 angewendet. Wird die Umgebungsvariable nicht explizit gesetzt, ist es systemabhängig, welches Scheduling-Verfahren gewählt wird. Ist kein schedule-parameter angegeben, wird das Default-Scheduling-Verfahren der entsprechenden OpenMP-Implementierung angewendet. Dieses ist in der Umgebungsvariable def-sched-var festgehalten und kann vom Programmierer nicht verändert werden. Der ordered-parameter Der ordered-parameter wird verwendet, wenn ein bestimmter Bereich innerhalb der Schleife erst ausgeführt werden darf, wenn alle vorherigen Iterationen diesen Bereich bereits ausgeführt haben. Zusätzlich zu der Angabe des ordered-parameters in der for-direktive wird dem entsprechende Bereich, für den die vorgeschriebene Reihenfolge gelten muss, noch eine ordered-direktive hinzugefügt: #pragma omp ordered { Anweisungsblock Diese ordered-direktive darf nur verwendet werden, wenn der for-direktive der ordered-parameter übergeben wurde. Eine mehrfache Verwendung innerhalb einer Schleife ist nicht zulässig. Erreicht ein Thread eine ordered-direktive, wartet er, bis alle vorherigen Iterationen den Anweisungsblock dieser Direktive ausgeführt haben und setzt erst dann seine Ausführung fort. Der nowait-parameter Am Ende der for-schleife werden alle Threads synchronisiert. Es warten also alle Threads, bis alle Iterationen der Schleife abgearbeitet sind. Soll auf diese Synchronisierung verzichtet werden, wird der for-direktive der Parameter nowait hinzugefügt. In einer for-direktive darf der nowait-parameter nicht mehrfach aufgeführt sein. In der kombinierten parallel for-direktive ist die Verwendung dieses Parameters allerdings nicht möglich, da am Ende der for-schleife alle Threads bis auf den Master-Thread beendet werden, bevor dieser die Ausführung fortsetzt. 13

16 Weitere Parameter der for-direktive Die übrigen Parameter (private, firstprivate, lastprivate, reduction) sind, wie in Abschnitt 3.1 erläutert, für die verschiedenen Varianten der Variablendeklarationen zuständig. Der Schleifenindex braucht hierbei nicht explizit einbezogen werden, da er automatisch als private Variable deklariert wird und mit dem aktuellen Index der entsprechenden Iteration initialisiert wird Beispiel Die for-direktive soll nun anhand eines Beispielprogramms, das alle Primzahlen von 2 bis ausgibt, veranschaulicht werden. Der Quelltext dieses zunächst seriellen Programms ist im Anhang unter A.2 zu finden. Zunächst werden die Integer- Variablen zahl, teiler und treffer deklariert, bevor als Überschrift das Wort Primzahlen ausgegeben wird. Im Anschluss daran wird mit Hilfe einer for-schleife jede Zahl von 2 bis überprüft, ob sie einen Teiler hat. Dafür wird die Variable treffer, die anzeigt, ob für den aktuellen Wert der Schleifenvariablen zahl ein Teiler gefunden wurde, zunächst auf 0 gesetzt. Innerhalb der for-schleife wird nun eine weitere for-schleife gestartet, die für alle Zahlen von 2 bis zahl überprüft, ob es sich um einen Teiler von zahl handelt und in diesem Fall der Variable treffer den Wert 1 zuweist. Nach Ausführung der inneren for-schleife wird zahl ausgegeben, wenn kein Teiler für den aktuellen Wert der Variable zahl gefunden wurde. Mit Hilfe von OpenMP soll dieses Programm, oder zumindest ein Teil von diesem, parallelisiert werden, um die Ausführungszeit zu senken. Hierfür ist zunächst die Datei omp.h durch den Befehl #include <omp.h> einzubinden. Im nächsten Schritt soll eine der beiden for-schleifen parallelisiert werden. Würde dafür die innere Schleife gewählt werden, so müssten bei jeder Iteration der äußeren Schleife zusätzliche Threads erzeugt (fork), am Ende der Schleife synchronisiert und wieder beendet werden (join). Um diesen Overhead zu vermeiden, wird die äußere Schleife parallelisiert, so dass insgesamt nur ein fork- und ein join-vorgang ausgeführt werden muss. Da der parallele Bereich nur aus der Schleife besteht, wird auf die kombinierte Schreibweise der parallel- und der for-direktive zurückgegriffen. Die Variable treffer muss für den parallelen Bereich als private Variable deklariert werden, da sie für jeden Wert der Indexvariable zahl einzeln bestimmt, ob diese einen Teiler hat oder nicht und somit nicht von einem anderen Thread geändert werden darf. Selbiges gilt für die Variable teiler, die Inderxvariable der inneren Schleife ist. Die Variable zahl wird automatisch als privat deklariert, da sie die Indexvariable der parallelisierten for-schleife ist. Eine Variante des parallelisierten Programms ist im Anhang unter A.3 dargestellt. Als Scheduling-Verfahren wurde die statische 14

17 Verteilung mit der Blockgröße 1 gewählt, um die mit steigender Indexvariable rechenlastiger werdenden Iterationen so auf die verschiedenen Threads zu verteilen, dass sich die Rechenlast möglichst gleichmäßig auf die Threads verteilt. Ist von gleich schnellen Prozessoren auszugehen, wird die statische gegenüber der dynamischen Verteilung bevorzugt, da bei dynamischer Verteilung nach Ausführung jeder Iteration zusätzlicher Overhead entsteht, um dem Thread die nächste Iteration zuzuweisen. Sind die Prozessoren des Systems unterschiedlich schnell, bietet sich hier eher eine dynamische Verteilung an. Die oben beschriebene Variante hat allerdings noch einen Nachteil: Die Primzahlen werden nicht mehr zwingend in strikt aufsteigender Reihenfolge ausgegeben. Das liegt daran, dass ein Thread, der gerade eine Iteration mit höherer Indexvariable als ein anderer Thread bearbeitet, möglicherweise früher die Anweisung die Zahl auszugeben erreicht als der andere Thread. Soll ein solches Verhalten unterbunden werden, muss die ordered-direktive hinzugefügt werden, die einen bestimmten Bereich einer Schleife erst dann ausführt, wenn alle vorherigen Iterationen diesen bereits ausgeführt haben. In diesem Falle ist also vor dem if -Konstrukt, das die Variable zahl ausgibt, wenn es sich um eine Primzahl handelt, die Direktive #pragma omp ordered einzufügen. Zusätzlich ist der parallel for-direktive am Beginn des parallelen Bereichs der Parameter ordered hinzuzufügen. Wird das Programm, dessen Quelltext im Anhang unter A.4 zu finden ist, nun ausgeführt, so werden die Primzahlen wie bei der seriellen Abarbeitung des Programms in aufsteigender Reihenfolge ausgegeben. Des Weiteren sollte beachtet werden, dass die Blockgröße für das Scheduling in diesem Fall 1 betragen sollte. Große Blöcke führen zu einer längeren Ausführungszeit, weil andere Threads warten müssen, bis ein Thread den ganzen Block abgearbeitet hat, bevor sie den synchronisierten Bereich betreten dürfen. Um die Verkürzung der Laufzeit durch die Parallelisierung des Programms mit OpenMP zu veranschaulichen, wurden die erläuterten drei Programmvarianten auf einem Personalcomputer mit einem Intel Core 2 Duo E6300-Prozessor ausgeführt. Da dieser Prozessor aus zwei Kernen besteht, kann er zwei Threads gleichzeitig ausführen. Jede der drei Programmvarianten wurde zehnmal ausgeführt und anschließend der arithmetische Mittelwert über die jeweiligen Ausführungszeiten gebildet, um Schwankungen bei der Ausführungszeit, die zum Beispiel durch gleichzeitig laufende Prozesse des Betriebssystems beeinflusst werden können, auszugleichen. Es ist zu erwarten, dass die Ausführungszeit der parallelen Version durch die Bearbeitung von zwei Prozessorkernen gegenüber der seriellen Version um fast die Hälfte sinkt. Nach Einfügen der ordered-direktive ist davon auszugehen, dass die Ausführungszeit im Vergleich zur Version mit der ungeordneten Ausgabe etwas 15

18 ansteigt, da der Synchronisationsaufwand steigt. Gegenüber der seriellen Abarbeitung ist jedoch auch hier eine Verkürzung der Ausführungszeit zu erwarten. Die Ausführungszeiten der einzelnen Durchläufe sind in Tabelle 2 im Anhang abzulesen. Die Ausführung der seriellen Version dauerte durchschnittlich 45,5 Sekunden, die parallele Version ohne ordered-direktive benötigte im Durchschnitt 23,8 Sekunden. Somit konnte durch die Verteilung der Abarbeitung der Iterationen auf zwei Threads, die gleichzeitig von zwei Prozessorkernen bearbeitet werden können, durchschnittlich über 47% der Ausführungszeit eingespart werden. Die Ausführungszeit der dritten Variation, bei der die Ausgabe der Primzahlen in strikt aufsteigender Reihenfolge erfolgt, betrug im Durchschnitt 25,9 Sekunden. Dass dieser Wert die durchschnittliche Ausführungszeit der zweiten Version um fast 9% übersteigt liegt darin begründet, dass durch die Synchronisation bei der Ausgabe Leerlaufzeiten der Threads entstehen, da sie erst weiter ausgeführt werden, wenn die anderen Threads den synchronisierten Bereich für die vorhergehenden Schleifeniterationen ausgeführt haben. Im Vergleich zur seriellen Abarbeitung liegt aber noch immer eine beträchtliche Verkürzung der Ausführungszeit um durchschnittlich 43% vor sections-direktive zur Parallelisierung von Abschnitten Mit OpenMP ist es möglich, verschiedene Programmabschnitte, die unabhängig voneinander sind, von mehreren Threads parallel abarbeiten zu lassen. Grundlage hierfür ist die sections-direktive Syntax Die Syntax der sections-direktive ist folgendermaßen aufgebaut: #pragma omp sections [Parameter [Parameter]...] { [#pragma omp section] Anweisungsblock [#pragma omp section Anweisungsblock. ] Die einsetzbaren Parameter sind in Tabelle 1 dargestellt. Besteht der Anweisungsblock des parallelen Bereichs ausschließlich aus den zu parallelisierenden Abschnitten, so können, analog zur Parallelisierung der for-schleife, die parallel- und die sections-direktive kombiniert werden: 16

19 #pragma omp parallel sections [Parameter [Parameter]...] Beschreibung Ist ein Bereich eines seriellen Programms so in Abschnitte aufteilbar, dass kein Abschnitt von den Ergebnissen eines vorherigen Abschnitts abhängt, so können diese Abschnitte parallel zueinander ausgeführt werden. Dem Bereich mit den zu parallelisierenden Abschnitten, der innerhalb eines parallel-konstruktes liegen muss, ist zu Beginn die sections-direktive mit den optionalen Parametern, die analog zur for-direktive der Variablendeklaration und der Thread-Synchronisation am Ende des Programmbereichs dienen, hinzuzufügen. Vor jedem einzelnen Abschnitt des Bereichs wird zusätzlich die section-direktive eingefügt. Nur für den ersten Abschnitt ist diese Angabe optional. Die Abschnitte werden bei der Ausführung des Bereichs auf die einzelnen Threads verteilt. Jeder Abschnitt wird genau einmal ausgeführt und jeder Thread führt keine, einen oder mehrere Abschnitte aus (abhängig vom Verhältnis Anzahl Abschnitte zu Anzahl Threads). Wie die Abschnitte auf die verschiedenen Threads verteilt werden ist implementierungsabhängig, so dass hierüber keine Aussagen getroffen werden können. Nachdem die Threads die Abschnitte abgearbeitet haben, werden sie, insofern kein nowait-parameter angegeben ist, synchronisiert, bevor die Ausführung des Programms fortgesetzt wird. Dieses Verfahren der Parallelisierung bietet sich insbesondere dann an, wenn durch andere Parallelisierungsverfahren (zum Beispiel mittels for-direktive) keine oder nur geringe Verkürzungen der Laufzeit in dem entsprechenden Bereich erreicht werden können, was beispielsweise dann der Fall ist, wenn große Teile innerhalb der einzelnen Abschnitte seriell ausgeführt werden müssen. 3.3 Anzahl Threads Ein paralleler Bereich wird von einer bestimmten Anzahl Threads ausgeführt. Diese Anzahl wird von mehreren Parameteren beeinflusst. Im ersten Schritt wird eine eventuell vorhandene if -Klausel in der parallel-direktive überprüft. Ist diese vorhanden und ihre Bedingung falsch, wird der Bereich nicht parallel sondern von nur einem Thread sequentiell abgearbeitet. Selbiges gilt für den Fall, dass sich die Direktive bereits in einem parallelen Bereich befindet und verschachtelte Parallelisierung deaktiviert ist oder kein weiterer Level der Parallelisierung unterstützt wird. Ob verschachtelte Parallelisierung unterstützt wird, ist abhängig vom Laufzeitsystem und kann durch den Aufruf von omp get nested() abgefragt werden, der 0 zurückliefert, wenn keine Verschachtelung unterstützt wird. Dieses kann beeinflusst werden, indem der entsprechenden Umgebungsvariable durch den Aufruf 17

20 von omp set nested(nested ) der Integer-Wert nested zugewiesen wird. Spricht weder die if -Klausel noch die Verschachtelung gegen eine Parallelisierung, kann durch die Funktion omp set dynmic(int dynamic threads) Einfluss auf die Anzahl der Threads genommen werden. Diese Funktion, die nur außerhalb eines parallelen Bereichs aufgerufen werden darf, ändert die Umgebungsvariable dyn-var, deren Wert durch Aufruf von omp get dynamic() ermittelt werden kann. Hat sie den Wert 0, so wird die Anzahl der Threads unabhängig von den Systemgegebenheiten folgendermaßen festgelegt: Wurde der parallel-direktive der Parameter num threads(anzahl ) übergeben, so bestimmt anzahl die Anzahl der Threads für den parallelen Bereich, ansonsten die Umgebungsvariable nthreads-var, die vom System initialisiert wird und außerhalb des parallelen Bereichs vom Programmierer durch die Funktion omp set num threads(int anzahl) verändert werden kann. Ist eine dynamische Anpassung an die Systemgegebenheiten durch das Laufzeitsystem erlaubt, d.h. dyn-var 0, wird erst zur Laufzeit festgelegt, von wie vielen Threads der parallele Bereich bearbeitet wird. Ist der Parameter num threads(anzahl ) angegeben, sind es höchstens anzahl Threads, ansonsten höchstens nthreadsvar Threads. 3.4 Koordination und Synchronisation von Threads In der Regel werden parallele Bereiche in einem OpenMP-Programm von mehreren Threads ausgeführt. Da diese auf gemeinsame Variablen zugreifen können, ist der Zugriff zu koordinieren. Hierfür stellt OpenMP verschiedene Direktiven bereit, die in diesem Abschnitt näher erläutert werden. Des Weiteren wird auf Direktiven eingegangen, mit deren Hilfe die Threads synchronisiert werden können Kritische Abschnitte Bei paralleler Programmierung auf Systemen mit gemeinsamem Speicher muss darauf geachtet werden, dass keine sogenannten Race-Conditions auftreten. Hierbei handelt es sich um Situationen, bei denen das Endergebnis davon abhängt, in welcher zeitlichen Abfolge die Threads auf den Prozessoren laufen. Eine Methode Race- Conditions zu vermeiden, ist der wechselseitige Ausschluss (mutual exclusion), d.h. ein Thread kann eine gemeinsam genutzte Variable nutzen, ohne dass ein anderer Thread zeitgleich auf diese zugreifen kann. Ein Abschnitt eines Programms, in dem auf gemeinsame Variablen zugegriffen wird, nennt sich kritischen Abschnitt [Ta03, S. 119]. Um Race-Conditions zu vermeiden bietet OpenMP die Möglichkeit, dass niemals 18

21 zwei Threads gleichzeitig einen kritischen Abschnitt ausführen können. Kritische Abschnitte sind dafür mit folgender Direktive zu kennzeichnen: #pragma omp critical [(name)] { kritischer Abschnitt Die Angabe von name ist optional. Alle kritischen Abschnitte ohne Namen bekommen vom System einen einheitlichen Namen zugewiesen. Trifft ein Thread auf einen kritischen Abschnitt, betritt er diesen erst, sobald sich kein anderer Thread in einem kritischen Abschnitt mit gleichem Namen befindet. Hierbei spielt es keine Rolle, ob die Threads einem gleichen Team zugeordnet sind. Bei der Deklarierung von Abschnitten zu kritischen Abschnitten ist darauf zu achten, dass Race-Conditions nur ausgeschlossen werden können, wenn alle Zugriffe auf eine gemeinsame Variable in gleichnamigen kritischen Abschnitten stehen. Werden hingegen zu viele Abschnitte zu kritischen Abschnitten deklariert, kann dieses zu vermeidbaren Performance- Einbußen führen Atomare Operationen Sei x eine gemeinsame Variable mit dem Wert 5. Führen nun zwei Threads parallel den Befehl x = x + 1 aus, so ist das Ergebnis nicht vorhersagbar. Das liegt darin begründet, dass x zuerst ausgelesen wird, der Wert inkrementiert wird und dann wieder nach x geschrieben wird. Wird der zweite Thread zwischen der Lese- und der Schreiboperation des ersten Threads komplett ausgeführt, so hat die Variable x nach Ausführung beider Threads den Wert 6, obwohl sich bei serieller Ausführung der beiden Threads der Wert 7 ergibt. Das beschriebene Problem kann in OpenMP mit den im vorherigen Abschnitt beschriebenen kritischen Abschnitten gelöst werden. Dieses lässt sich in OpenMP allerdings effizienter lösen, wenn der kritische Abschnitt ausschließlich aus einer Zuweisung besteht, die eine der folgenden Formen annimmt: x++, ++x, x--, --x, x binop= skalarer Ausdruck, wobei binop {+,,, /, &,ˆ,, <<, >> und skalarer Ausdruck nicht auf x referenzieren darf. Diese Speicherzugriffe können als atomare Operation deklariert werden, so dass sie in einem Schritt ausgeführt werden ohne dabei unterbrochen zu werden. Die OpenMP-Direktive zur Deklarierung einer Zuweisung als atomare Operation hat folgende Syntax: 19

22 #pragma omp atomic Zuweisung Die Zuweisung muss einer der oben genannten Operationen entsprechen. Das Berechnen von skalarer Ausdruck ist nicht Teil der atomaren Operation Synchronisation Mit Hilfe des barrier-konstruktes ist es möglich, Threads zeitlich zu synchronisieren. Die zugehörige Syntax lautet: #pragma omp barrier Erreicht ein Thread in einem parallelen Bereich diese Direktive, beginnt er die Abarbeitung der nachfolgenden Anweisungen erst, wenn alle Threads des Teams diese Direktive erreicht haben. Die Direktive wird zum Beispiel dann eingesetzt, wenn ein Abschnitt auf die Ergebnisse aller Threads eines vorherigen Abschnittes aufbaut. Es ist sicherzustellen, dass diese Direktive entweder von allen oder von keinem Thread erreicht wird. Sie darf somit beispielsweise nicht in einem if -Konstrukt stehen, wenn einige Threads die Bedingung des if -Konstruktes erfüllen und andere nicht, da dann nicht alle Threads die Direktive erreichen können und somit eine Verklemmung (Deadlock) entsteht. Es werden nur alle Threads des jeweiligen parallelen Bereichs synchronisiert. Das gilt auch, wenn mehrere parallelen Bereiche vorhanden sind, was zum Beispiel bei verschachtelter Parallelisierung auftreten kann Ausführung ausschließlich durch den Master-Thread Die master-direktive ermöglicht, dass ein Programmabschnitt in einem parallelen Bereich ausschließlich durch den Master-Thread des Teams ausgeführt wird. Ihre Syntax ist folgendermaßen: #pragma omp master { Anweisungsblock Erreicht der Master-Thread die Direktive, bearbeitet er den Anweisungsblock. Liegt die Direktive in einem verschachtelten parallelen Bereich, so ist hiermit der Master-Thread des innersten parallelen Bereiches gemeint. Alle anderen Threads des Teams ignorieren den Anweisungsblock und setzen die Ausführung mit dem ersten Befehl nach dem Anweisungsblock fort. Am Ende des Blockes erfolgt keine Synchronisierung. Im Gegensatz zur barrier-direktive ist es bei der master-direktive nicht notwendig, dass diese von allen Threads erreicht wird. 20

23 Kapitel 4: Zusammenfassung und Ausblick 4 Zusammenfassung und Ausblick OpenMP ist ein Schnittstelle zur parallelen Programmierung auf Multiprozessorsystemen mit gemeinsamem Speicher. Sie stellt Compilerdirektiven, Bibliotheksfunktionen und Umgebungsvariablen für die Programmiersprachen C, C++ und Fortran zur Verfügung. Der Programmierer kann von den zugrunde liegenden Threads abstrahieren, da OpenMP das Erstellen und Beenden der Threads nach dem Fork-join-Prinzip und die Verwaltung der Threads übernimmt. Soll ein Programm-Abschnitt von mehreren Prozessoren parallel abgearbeitet werden, sind diesem Abschnitt eine parallel-direktive voranzustellen und gegebenfalls, in Abhängigkeit von der Art der Parallelisierung, wie zum Beispiel Mehrfachausführung des gleichen Codes oder arbeitsteilende Aufteilung von Schleifeniterationen, weitere Direktiven hinzuzufügen. Hierbei ist der Programmierer dafür verantwortlich, dass keine Konflikte, Deadlocks und Race Conditions auftreten. Für diesen Zweck stellt OpenMP ebenfalls Direktiven zur Verfügung, mit denen beispielsweise kritische Abschnitte oder atomare Operationen deklariert werden können. Wird das Programm von einem Compiler ausgeführt, der OpenMP nicht unterstützt, so werden die OpenMP-Direktiven ignoriert und das Programm wird seriell ausgeführt. In modernen Supercomputern ist es möglich, MPI und OpenMP zu kombinieren. Hierbei wird die Arbeit mittels MPI auf die verschiedenen Multiprozessorsysteme verteilt, die die Berechnungen dann durch Anwendung von OpenMP parallelisieren. Im Hinblick auf weitere Performance-Steigerungen wird die Parallelisierung von Programmen zukünftig weiter an Bedeutung gewinnen. Eine weitere Geschwindigkeitssteigerung durch schnellere Prozessoren wird bald an ihre physikalischen Grenzen stoßen, da der Abstand zwischen Prozessor und Cache nicht beliebig verkleinert werden kann und die Daten sich nicht schneller als mit Lichtgeschwindigkeit ausbreiten können. Somit kann die Performance insbesondere durch die Verteilung der Arbeit auf mehrere Prozessoren, beispielsweise durch Anwendung von OpenMP, gesteigert werden. 21

OpenMP - Threading- Spracherweiterung für C/C++ Matthias Klein, Michael Pötz Systemprogrammierung 15. Juni 2009

OpenMP - Threading- Spracherweiterung für C/C++ Matthias Klein, Michael Pötz Systemprogrammierung 15. Juni 2009 - Threading- Spracherweiterung für C/C++ Matthias Klein, Michael Pötz Systemprogrammierung 15. Juni 2009 Grundlagen der Parallelen Programmierung Hardware Threads vs. Prozesse Kritische Abschnitte Lange

Mehr

Parallel Regions und Work-Sharing Konstrukte

Parallel Regions und Work-Sharing Konstrukte Parallel Regions und Work-Sharing Konstrukte Um eine Parallelisierung von größeren Programmabschnitten, als es einzelne Schleifen sind, zu ermöglichen, stellt OpenMP als allgemeinstes Konzept die Parallel

Mehr

OpenMP. Viktor Styrbul

OpenMP. Viktor Styrbul OpenMP Viktor Styrbul Inhaltsverzeichnis Was ist OpenMP Warum Parallelisierung Geschichte Merkmale von OpenMP OpenMP-fähige Compiler OpenMP Ausführungsmodell Kernelemente von OpenMP Zusammenfassung Was

Mehr

Einige Grundlagen zu OpenMP

Einige Grundlagen zu OpenMP Einige Grundlagen zu OpenMP Stephanie Friedhoff, Martin Lanser Mathematisches Institut Universität zu Köln 22. Juni 2016 Überblick Was ist OpenMP? Basics Das OpenMP fork-join-modell Kompilieren und Ausführen

Mehr

1. Einführung in OpenMP

1. Einführung in OpenMP 1. Einführung in OpenMP Übersicht Einführung Homogene und inhomogene Arbeitsverteilung Rekursive Parallelität Beispiele Parallele Programmierung 1 Nicolas Maillard, Marcus Ritt 1 Überblick OpenMP: Vereinfachte

Mehr

Parallele Programmierung mit OpenMP

Parallele Programmierung mit OpenMP Parallele Programmierung mit OpenMP - Eine kurze Einführung - 11.06.2003 RRZN Kolloquium SS 2003 1 Gliederung 1. Grundlagen 2. Programmiermodell 3. Sprachkonstrukte 4. Vergleich MPI und OpenMP 11.06.2003

Mehr

Praktikum: Paralleles Programmieren für Geowissenschaftler

Praktikum: Paralleles Programmieren für Geowissenschaftler Praktikum: Paralleles Programmieren für Geowissenschaftler Prof. Thomas Ludwig, Hermann Lenhart, Ulrich Körner, Nathanael Hübbe hermann.lenhart@zmaw.de OpenMP Einführung I: Allgemeine Einführung Prozesse

Mehr

Java 8. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Oktober 2014 JAV8

Java 8. Elmar Fuchs Grundlagen Programmierung. 1. Ausgabe, Oktober 2014 JAV8 Java 8 Elmar Fuchs Grundlagen Programmierung 1. Ausgabe, Oktober 2014 JAV8 5 Java 8 - Grundlagen Programmierung 5 Kontrollstrukturen In diesem Kapitel erfahren Sie wie Sie die Ausführung von von Bedingungen

Mehr

Threads und OpenMP. Frank Mietke <frank.mietke@informatik.tu-chemnitz.de> Cluster- & Gridcomputing Frank Mietke 7/4/04

Threads und OpenMP. Frank Mietke <frank.mietke@informatik.tu-chemnitz.de> Cluster- & Gridcomputing Frank Mietke 7/4/04 Threads und OpenMP Frank Mietke 1 Ziel der Vorlesungen Einführung in Threads Programmierung mit Threads Einführung in OpenMP Programmierung mit OpenMP 2 Was ist

Mehr

JavaScript. Dies ist normales HTML. Hallo Welt! Dies ist JavaScript. Wieder normales HTML.

JavaScript. Dies ist normales HTML. Hallo Welt! Dies ist JavaScript. Wieder normales HTML. JavaScript JavaScript wird direkt in HTML-Dokumente eingebunden. Gib folgende Zeilen mit einem Texteditor (Notepad) ein: (Falls der Editor nicht gefunden wird, öffne im Browser eine Datei mit der Endung

Mehr

Schachtelung der 2. Variante (Bedingungs-Kaskade): if (B1) A1 else if (B2) A2 else if (B3) A3 else if (B4) A4 else A

Schachtelung der 2. Variante (Bedingungs-Kaskade): if (B1) A1 else if (B2) A2 else if (B3) A3 else if (B4) A4 else A 2.4.6. Kontrollstrukturen if-anweisung: Bedingte Ausführung (Verzweigung) 2 Varianten: if (Bedingung) Anweisung (Anweisung = einzelne Anweisung oder Block) Bedeutung: die Anweisung wird nur ausgeführt,

Mehr

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 2

Modul Entscheidungsunterstützung in der Logistik. Einführung in die Programmierung mit C++ Übung 2 Fakultät Verkehrswissenschaften Friedrich List, Professur für Verkehrsbetriebslehre und Logistik Modul Entscheidungsunterstützung in der Logistik Einführung in die Programmierung mit C++ Übung 2 SS 2016

Mehr

S. d. I.: Programieren in C Folie 4-1. im Gegensatz zu Pascal gibt es in C kein Schlüsselwort "then"

S. d. I.: Programieren in C Folie 4-1. im Gegensatz zu Pascal gibt es in C kein Schlüsselwort then S. d. I.: Programieren in C Folie 4-1 4 Anweisungen 4.1 if-anweisung 1) if (Ausdruck) 2) if (Ausdruck) } else im Gegensatz zu Pascal gibt es in C kein Schlüsselwort "then" es wird nur der numerische Wert

Mehr

Webbasierte Programmierung

Webbasierte Programmierung Webbasierte Programmierung Eine Einführung mit anschaulichen Beispielen aus der HTML5-Welt apl. Prof. Dr. Achim Ebert Inhalt Kapitel 6: JavaScript Kontrollstrukturen Verzweigungen Einseitig, zweiseitig,

Mehr

PHP 5.4 ISBN 978-3-86249-327-2. Stephan Heller, Andreas Dittfurth 1. Ausgabe, September 2012. Grundlagen zur Erstellung dynamischer Webseiten GPHP54

PHP 5.4 ISBN 978-3-86249-327-2. Stephan Heller, Andreas Dittfurth 1. Ausgabe, September 2012. Grundlagen zur Erstellung dynamischer Webseiten GPHP54 PHP 5.4 Stephan Heller, Andreas Dittfurth 1. Ausgabe, September 2012 Grundlagen zur Erstellung dynamischer Webseiten ISBN 978-3-86249-327-2 GPHP54 5 PHP 5.4 - Grundlagen zur Erstellung dynamischer Webseiten

Mehr

Schleifenanweisungen

Schleifenanweisungen Schleifenanweisungen Bisher: sequentielle Abarbeitung von Befehlen (von oben nach unten) Nun: Befehle mehrfach ausführen (= Programmschleife): for-anweisung - wenn feststeht, wie oft z.b.: eine Berechnung

Mehr

Algorithmen & Programmierung. Steuerstrukturen im Detail Selektion und Iteration

Algorithmen & Programmierung. Steuerstrukturen im Detail Selektion und Iteration Algorithmen & Programmierung Steuerstrukturen im Detail Selektion und Iteration Selektion Selektion Vollständige einfache Selektion Wir kennen schon eine Möglichkeit, Selektionen in C zu formulieren: if

Mehr

Programmierung mit C Zeiger

Programmierung mit C Zeiger Programmierung mit C Zeiger Zeiger (Pointer)... ist eine Variable, die die Adresse eines Speicherbereichs enthält. Der Speicherbereich kann... kann den Wert einer Variablen enthalten oder... dynamisch

Mehr

Sequentielle Programm- / Funktionsausführung innerhalb eines Prozesses ( thread = Ausführungsfaden )

Sequentielle Programm- / Funktionsausführung innerhalb eines Prozesses ( thread = Ausführungsfaden ) Threads Sequentielle Programm- / Funktionsausführung innerhalb eines Prozesses ( thread = Ausführungsfaden ) Ein thread bearbeitet eine sequentielle Teilaufgabe innerhalb eines Prozesses Mehrere nebenläufige

Mehr

4. Parallelprogrammierung

4. Parallelprogrammierung 4. Parallelprogrammierung AlDaBi Prak4kum David Weese 2010/11 Enrico Siragusa WS 2011/12 Inhalt Einführung in Parallelität OpenMP Bemerkungen zur P- Aufgabe EINFÜHRUNG IN PARALLELITÄT Folien z.t. aus VL

Mehr

Einfache Rechenstrukturen und Kontrollfluss II

Einfache Rechenstrukturen und Kontrollfluss II Einfache Rechenstrukturen und Kontrollfluss II Martin Wirsing in Zusammenarbeit mit Moritz Hammer und Axel Rauschmayer http://www.pst.informatik.uni-muenchen.de/lehre/ss06/infoii/ SS 06 Ziele Lernen imperative

Mehr

GI Vektoren

GI Vektoren Vektoren Problem: Beispiel: viele Variablen vom gleichen Typ abspeichern Text ( = viele char-variablen), Ergebnisse einer Meßreihe ( = viele int-variablen) hierfür: Vektoren ( = Arrays = Feld ) = Ansammlung

Mehr

3. Anweisungen und Kontrollstrukturen

3. Anweisungen und Kontrollstrukturen 3. Kontrollstrukturen Anweisungen und Blöcke 3. Anweisungen und Kontrollstrukturen Mit Kontrollstrukturen können wir den Ablauf eines Programmes beeinflussen, z.b. ob oder in welcher Reihenfolge Anweisungen

Mehr

CUDA. Jürgen Pröll. Multi-Core Architectures and Programming. Friedrich-Alexander-Universität Erlangen-Nürnberg Jürgen Pröll 1

CUDA. Jürgen Pröll. Multi-Core Architectures and Programming. Friedrich-Alexander-Universität Erlangen-Nürnberg Jürgen Pröll 1 CUDA Jürgen Pröll Multi-Core Architectures and Programming Jürgen Pröll 1 Image-Resize: sequentiell resize() mit bilinearer Interpolation leicht zu parallelisieren, da einzelne Punkte voneinander unabhängig

Mehr

Repetitorium Informatik (Java)

Repetitorium Informatik (Java) Repetitorium Informatik (Java) Tag 6 Lehrstuhl für Informatik 2 (Programmiersysteme) Übersicht 1 Klassen und Objekte Objektorientierung Begrifflichkeiten Deklaration von Klassen Instanzmethoden/-variablen

Mehr

VORKURS INFORMATIK EINE EINFÜHRUNG IN JAVASCRIPT

VORKURS INFORMATIK EINE EINFÜHRUNG IN JAVASCRIPT 4. Oktober 2016 VORKURS INFORMATIK EINE EINFÜHRUNG IN JAVASCRIPT Benjamin Förster Institut für Informatik, Informations- und Medientechnik INHALT 1. HTML5 Einstieg HTML5 2. Einführung in JavaScript Zeichnen

Mehr

Einführung in die Programmierung Wintersemester 2011/12

Einführung in die Programmierung Wintersemester 2011/12 Einführung in die Programmierung Wintersemester 2011/12 Prof. Dr. Günter Rudolph Lehrstuhl für Algorithm Engineering Fakultät für Informatik TU Dortmund : Kontrollstrukturen Inhalt Wiederholungen - while

Mehr

Universität Karlsruhe (TH)

Universität Karlsruhe (TH) Universität Karlsruhe (TH) Forschungsuniversität gegründet 1825 OpenMP-Programmierung Teil I Multikern-Praktikum Wintersemester 06-07 Inhalt Was ist OpenMP? Parallele Regionen Konstrukte zur Arbeitsteilung

Mehr

Schleifen in C/C++/Java

Schleifen in C/C++/Java Schleifen in C/C++/Java Alle 3 Sprachen stellen mindestens die folgenden 3 Schleifenkonstruktionen zur Verfügung. In C gibt es auch keine weiteren, C++, Java und C# haben noch weitere nützliche Varianten.

Mehr

Prozeduren und Funktionen

Prozeduren und Funktionen OSZ Handel I - Gymnasiale Oberstufe (Abt. V) In Anlehnung an: Duden Informatik (3.Auflage, Dudenverlag, 2001, S. 477). Prozeduren und Funktionen Fach: Informatik Parameter sind Platzhalter in einer Prozedur

Mehr

Parallele Programmierung mit OpenMP

Parallele Programmierung mit OpenMP Parallele Programmierung mit OpenMP Wolfgang Dautermann FH Joanneum Chemnitzer Linuxtage 2008 1 Motivation 2 OpenMP Übersicht 3 Hello World - der erste Code 4 OpenMP-Compilerdirektiven Threaderzeugung

Mehr

Projektseminar Parallele Programmierung

Projektseminar Parallele Programmierung HTW Dresden WS 2014/2015 Organisatorisches Praktikum, 4 SWS Do. 15:00-18:20 Uhr, Z136c, 2 Doppelstunden o.g. Termin ist als Treffpunkt zu verstehen Labore Z 136c / Z 355 sind Montag und Donnerstag 15:00-18:20

Mehr

Prof. W. Henrich Seite 1

Prof. W. Henrich Seite 1 Klasse - ist ein benutzerdefinierter Datentyp (Referenztyp) - hat Datenelemente - hat Methoden - Konstruktor ist spezielle Methode zum Erstellen eines Objektes vom Typ der Klasse (Instanz) - jede Klasse

Mehr

Programmieren mit OpenMP

Programmieren mit OpenMP Programmieren mit OpenMP Dr. Victor Pankratius David J. Meder IPD Tichy Lehrstuhl für Programmiersysteme KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH) Inhalt Was

Mehr

C.3 Funktionen und Prozeduren

C.3 Funktionen und Prozeduren C3 - Funktionen und Prozeduren Funktionsdeklarationen in Pascal auch in Pascal kann man selbstdefinierte Funktionen einführen: Funktionen und Prozeduren THEN sign:= 0 Funktion zur Bestimmung des Vorzeichens

Mehr

Test (Lösungen) Betriebssysteme, Rechnernetze und verteilte Systeme

Test (Lösungen) Betriebssysteme, Rechnernetze und verteilte Systeme Seite 1 Test (Lösungen) Betriebssysteme, Rechnernetze und verteilte Systeme 1 11.07.2007 Hinweise: Bevor Sie mit der Bearbeitung der Aufgaben beginnen, müssen Sie auf allen Blättern Ihren Namen und Ihre

Mehr

(a) Wie unterscheiden sich synchrone und asynchrone Unterbrechungen? (b) In welchen drei Schritten wird auf Unterbrechungen reagiert?

(a) Wie unterscheiden sich synchrone und asynchrone Unterbrechungen? (b) In welchen drei Schritten wird auf Unterbrechungen reagiert? SoSe 2014 Konzepte und Methoden der Systemsoftware Universität Paderborn Fachgebiet Rechnernetze Präsenzübung 2 2014-04-28 bis 2014-05-02 Aufgabe 1: Unterbrechungen (a) Wie unterscheiden sich synchrone

Mehr

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen:

Erweiterung der Aufgabe. Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: VBA Programmierung mit Excel Schleifen 1/6 Erweiterung der Aufgabe Die Notenberechnung soll nicht nur für einen Schüler, sondern für bis zu 35 Schüler gehen: Es müssen also 11 (B L) x 35 = 385 Zellen berücksichtigt

Mehr

Anleitung für zwei C++ - Openmp - Beispiele auf der NWZSuperdome

Anleitung für zwei C++ - Openmp - Beispiele auf der NWZSuperdome Anleitung für zwei C++ - Openmp - Beispiele auf der NWZSuperdome (Timo Heinrich, t_hein03@uni-muenster.de) Inhaltsverzeichnis: 0.Einleitung 1.Teil: Helloworldprogramm 1.1 Quellcode: Helloworld.cpp 1.2

Mehr

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden Kapitel 8 Programmierkurs Birgit Engels Anna Schulze Zentrum für Angewandte Informatik Köln Objektorientierte Programmierung Methoden Überladen von Methoden Der this-zeiger Konstruktoren Vererbung WS 07/08

Mehr

Objektorientierte Programmierung

Objektorientierte Programmierung Objektorientierte Programmierung Eine Einführung mit anschaulichen Beispielen aus der Java-Welt apl. Prof. Dr. Achim Ebert Inhalt Kapitel 3: Kontrollstrukturen Einfache Anweisungen Anweisungsblöcke Steuerung

Mehr

Programmieren I + II Regeln der Code-Formatierung

Programmieren I + II Regeln der Code-Formatierung Technische Universität Braunschweig Dr. Werner Struckmann Institut für Programmierung und Reaktive Systeme WS 2016/2017, SS 2017 Programmieren I + II Regeln der Code-Formatierung In diesem Dokument finden

Mehr

Parallele Systeme. 1 Einführung 2 1.1 Durchführung der erweiterten Übung... 3 1.2 OpenMP... 3

Parallele Systeme. 1 Einführung 2 1.1 Durchführung der erweiterten Übung... 3 1.2 OpenMP... 3 Lehrstuhl für Informatik 12 Cauerstraße 11 91058 Erlangen TECHNISCHE FAKULTÄT 1. Erweiterte Übung zur Vorlesung Parallele Systeme Inhaltsverzeichnis 1 Einführung 2 1.1 Durchführung der erweiterten Übung..........................

Mehr

Einstieg in die Informatik mit Java

Einstieg in die Informatik mit Java 1 / 34 Einstieg in die Informatik mit Java Klassen mit Instanzmethoden Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 34 1 Definition von Klassen 2 Methoden 3 Methoden

Mehr

Kapitel 3: Variablen

Kapitel 3: Variablen Kapitel 3: Variablen Thema: Programmieren Seite: 1 Kapitel 3: Variablen Im letzten Kapitel haben wir gelernt, bestimmte Ereignisse zu wiederholen solange eine Bedingung erfüllt ist. Nun möchten wir aber

Mehr

Grundlagen der Programmiersprache C++

Grundlagen der Programmiersprache C++ / TU Braunschweig Grundlagen der Programmiersprache C++ Um den Studierenden den Einstieg in die FE-Programmierung zu erleichtern werden die wesentlichen Elemente eines C-Programmes beschrieben, soweit

Mehr

Inhaltsverzeichnis. Grundbegriffe der C-Programmierung Für den HI-TECH C-Compiler

Inhaltsverzeichnis. Grundbegriffe der C-Programmierung Für den HI-TECH C-Compiler Inhaltsverzeichnis Grundbegriffe der C-Programmierung 1. Grundsätzliches... 2 1.1 Darstellung von Werten... 2 1.1.1 Dezimale Zahlendarstellung... 2 1.1.2 Binäre Zahlendarstellung... 3 1.1.3 Hexadezimale

Mehr

Programmierkurs Python I

Programmierkurs Python I Programmierkurs Python I Michaela Regneri & Stefan Thater Universität des Saarlandes FR 4.7 Allgemeine Linguistik (Computerlinguistik) Winter 2010/11 Übersicht Kurze Wiederholung: while Sammeltypen (kurz

Mehr

Kapitel 5. Programmierkurs. Kontrollstrukturen. Arten von Kontrollstrukturen. Kontrollstrukturen Die if-anweisung Die switch-anweisung

Kapitel 5. Programmierkurs. Kontrollstrukturen. Arten von Kontrollstrukturen. Kontrollstrukturen Die if-anweisung Die switch-anweisung Kapitel 5 Programmierkurs Birgit Engels, Anna Schulze ZAIK Universität zu Köln Kontrollstrukturen Die if-anweisung Die switch-anweisung Die for-schleife Die while-schleife Die do-schleife WS 7/8 /55 Kontrollstrukturen

Mehr

PROGRAMMIERUNG IN JAVA

PROGRAMMIERUNG IN JAVA PROGRAMMIERUNG IN JAVA ZUWEISUNGEN (1) Deklaration nennt man die Ankündigung eines Platzhalters (Variablen) und Initialisierung die erste Wertvergabe bzw. die konkrete Erstellung des Platzhalters. In einem

Mehr

Entwurf von Algorithmen - Kontrollstrukturen

Entwurf von Algorithmen - Kontrollstrukturen Entwurf von Algorithmen - Kontrollstrukturen Eine wichtige Phase in der Entwicklung von Computerprogrammen ist der Entwurf von Algorithmen. Dieser Arbeitsschritt vor dem Schreiben des Programmes in einer

Mehr

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik

OOP und Angewandte Mathematik. Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik Eine Einführung in die Anwendung objektorientierter Konzepte in der angewandten Mathematik WS 2011/12 Inhalt Test-Besprechung! Ziele verdeutlichen Große Bild von OOP Wiederholung: Einbettung als Technik

Mehr

Bei for-schleifen muss man nur immer bedenken, dass die letzte Anweisung immer erst nach der Ausführung der restlichen Anweisungen der Schleife

Bei for-schleifen muss man nur immer bedenken, dass die letzte Anweisung immer erst nach der Ausführung der restlichen Anweisungen der Schleife 303 Bei for-schleifen muss man nur immer bedenken, dass die letzte Anweisung immer erst nach der Ausführung der restlichen Anweisungen der Schleife durchgeführt wird. 304 305 for-schleifen sind in Aktivitätsdiagrammen

Mehr

Programmieren für Wirtschaftswissenschaftler SS 2015

Programmieren für Wirtschaftswissenschaftler SS 2015 DEPARTMENT WIRTSCHAFTSINFORMATIK FACHBEREICH WIRTSCHAFTSWISSENSCHAFT Programmieren für Wirtschaftswissenschaftler SS 2015 Lucian Ionescu Blockveranstaltung 16.03 27.3.2015 3. Verzweigungen und Schleifen

Mehr

OpenMP am Beispiel der Matrizenmultiplikation

OpenMP am Beispiel der Matrizenmultiplikation OpenMP am Beispiel der Matrizenmultiplikation David J. Meder, Dr. Victor Pankratius IPD Tichy Lehrstuhl für Programmiersysteme KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe

Mehr

ModProg 15-16, Vorl. 5

ModProg 15-16, Vorl. 5 ModProg 15-16, Vorl. 5 Richard Grzibovski Nov. 18, 2015 1 / 29 Übersicht Übersicht 1 Logische Operationen 2 Priorität 3 Verzweigungen 4 Schleifen 2 / 29 Logische Werte Hauptkonzept: Besitzt ein C-Ausdruck

Mehr

Übungen zur Vorlesung Wissenschaftliches Rechnen I. Grundelemente von Java. Eine Anweisung. wird mit dem Wertzuweisungsoperator = geschrieben.

Übungen zur Vorlesung Wissenschaftliches Rechnen I. Grundelemente von Java. Eine Anweisung. wird mit dem Wertzuweisungsoperator = geschrieben. Eine Anweisung wird mit dem Wertzuweisungsoperator = geschrieben. Eine Anweisung wird mit dem Wertzuweisungsoperator = geschrieben. Daher ist y = x + 5.6; keine Gleichung, sondern die Anweisung den Wert

Mehr

Vorlesung Programmieren

Vorlesung Programmieren Vorlesung Programmieren 3. Kontrollstrukturen 04.11.2015 Prof. Dr. Ralf H. Reussner Version 1.1 LEHRSTUHL FÜR SOFTWARE-DESIGN UND QUALITÄT (SDQ) INSTITUT FÜR PROGRAMMSTRUKTUREN UND DATENORGANISATION (IPD),

Mehr

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny

Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny Programmiersprache 1 (C++) Prof. Dr. Stefan Enderle NTA Isny 5. Kontrollstrukturen Allgemein Kontrollstrukturen dienen zur Steuerung des Programmablaufs. (Bemerkung: C und C++ besitzen die selben Kontrollstrukturen.)

Mehr

Variablen in MATLAB. Unterschiede zur Mathematik: Symbolisches und numerisches Rechnen. Skriptdateien. for-schleifen.

Variablen in MATLAB. Unterschiede zur Mathematik: Symbolisches und numerisches Rechnen. Skriptdateien. for-schleifen. Variablen in MATLAB. Unterschiede zur Mathematik: Symbolisches und numerisches Rechnen. Skriptdateien. for-schleifen. Wir wollen uns heute dem Thema Variablen widmen und uns damit beschäftigen, wie sich

Mehr

1 Organisatorisches. 2 Compilezeit- und Laufzeitfehler. 3 Exceptions. 4 Try-Catch-Finally

1 Organisatorisches. 2 Compilezeit- und Laufzeitfehler. 3 Exceptions. 4 Try-Catch-Finally Themen der Übung CoMa-Übung VI 1 Organisatorisches Compilezeit- und Laufzeitfehler 3 Try-Catch-Finally TU Berlin 8.11.01 Bewertung der OA 5 fehlerhaft, Madeleine arbeitet dran CoMa-Übung VI (TU Berlin)

Mehr

Shared-Memory Parallelisierung von C++ Programmen

Shared-Memory Parallelisierung von C++ Programmen Shared-Memory Parallelisierung von C++ Programmen 9. Februar 2006 1 Übersicht Ergebnisse Zusammenfassung 2 3 Übersicht Ergebnisse Zusammenfassung Übersicht Verbreitete Parallelisierungstechniken für Shared-Memory:

Mehr

Aufbau von Klassen. class punkt {...

Aufbau von Klassen. class punkt {... Einführung in C++ Aufbau von Klassen Eine wird mit dem Schlüsselwort class eingeleitet, und endet mit einem Semikolon. Der Inhalt wird zwischen geschweiften Klammern geschrieben. class punkt {... ; Im

Mehr

Einstieg in die Informatik mit Java

Einstieg in die Informatik mit Java 1 / 26 Einstieg in die Informatik mit Java Felder Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 26 1 Was sind Felder? 2 Vereinbarung von Feldern 3 Erzeugen von Feldern

Mehr

Dynamisches Huffman-Verfahren

Dynamisches Huffman-Verfahren Dynamisches Huffman-Verfahren - Adaptive Huffman Coding - von Michael Brückner 1. Einleitung 2. Der Huffman-Algorithmus 3. Übergang zu einem dynamischen Verfahren 4. Der FGK-Algorithmus 5. Überblick über

Mehr

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet C++ Grundlagen ++ bedeutet Erweiterung zum Ansi C Standard Hier wird eine Funktion eingeleitet Aufbau: In dieser Datei stehen die Befehle, die gestartet werden, wenn das Programm gestartet wird Int main()

Mehr

Erwin Grüner 09.02.2006

Erwin Grüner 09.02.2006 FB Psychologie Uni Marburg 09.02.2006 Themenübersicht Folgende Befehle stehen in R zur Verfügung: {}: Anweisungsblock if: Bedingte Anweisung switch: Fallunterscheidung repeat-schleife while-schleife for-schleife

Mehr

Inhaltsüberblick. I. Grundbegriffe - Objekte und Klassen. Organisatorisches. I. Grundbegriffe - Objektorientierte Konzepte

Inhaltsüberblick. I. Grundbegriffe - Objekte und Klassen. Organisatorisches. I. Grundbegriffe - Objektorientierte Konzepte Grundkonzepte Objektorientierter Programmierung Nicole Himmerlich FSU Jena mit Java, Oberon-2, Object-Pascal und Python Inhaltsüberblick I. Grundbegriffe 1) Kopplung 2) Datenkaspelung 3) Konstruktor 4)

Mehr

2.5 Programmstrukturen Entscheidung / Alternative

2.5 Programmstrukturen Entscheidung / Alternative Entscheidung, ob der folgende Anweisungsblock ausgeführt wird oder ein alternativer Block Entscheidung ob die Bedingung wahr oder falsch (True / False) ist Syntax: 2.5 Programmstrukturen 2.5.1 Entscheidung

Mehr

Probeklausur: Programmierung WS04/05

Probeklausur: Programmierung WS04/05 Probeklausur: Programmierung WS04/05 Name: Hinweise zur Bearbeitung Nimm Dir für diese Klausur ausreichend Zeit, und sorge dafür, dass Du nicht gestört wirst. Die Klausur ist für 90 Minuten angesetzt,

Mehr

Schleifen in Javascript

Schleifen in Javascript Schleifen in Javascript Jobst-Hartmut Lüddecke 3. April 2013 Zusammenfassung In dieser Lektion geht es um Schleifen (engl. loop). Diese Schleifen sind in jeder Programmiersprache das beste Werkzeug für

Mehr

Parallele Programmierung mit OpenMP

Parallele Programmierung mit OpenMP Parallele Programmierung mit OpenMP Wolfgang Dautermann FH Joanneum Chemnitzer Linuxtage 2009 1 Motivation 2 OpenMP Übersicht 3 Hello World - der erste Code 4 OpenMP-Compilerdirektiven Threaderzeugung

Mehr

MSDN Webcast: Parallelprogrammierung mit der Task Parallel Library für.net (Teil 1) Presenter: Bernd Marquardt

MSDN Webcast: Parallelprogrammierung mit der Task Parallel Library für.net (Teil 1) Presenter: Bernd Marquardt MSDN Webcast: Parallelprogrammierung mit der Task Parallel Library für.net (Teil 1) Presenter: Bernd Marquardt berndm@go-sky.de www.go-sky.de Die Serie: 5 Teile Teil 1: Einführung, Amdahl s Gesetz, Data

Mehr

Bedienung von BlueJ. Klassenanzeige

Bedienung von BlueJ. Klassenanzeige Im Folgenden werden wichtige Funktionen für den Einsatz von BlueJ im Unterricht beschrieben. Hierbei wird auf den Umgang mit Projekten, Klassen und Objekten eingegangen. Abgeschlossen wird dieses Dokument

Mehr

Programmieren I. Kapitel 5. Kontrollfluss

Programmieren I. Kapitel 5. Kontrollfluss Programmieren I Kapitel 5. Kontrollfluss Kapitel 5: Kontrollfluss Ziel: Komplexere Berechnungen im Methodenrumpf Ausdrücke und Anweisungen Fallunterscheidungen (if, switch) Wiederholte Ausführung (for,

Mehr

Moderne Betriebssysteme. Kapitel 8. Kapitel 8. Folie: 1. Multiprozessorsysteme. Autor: Andrew S. Tanenbaum

Moderne Betriebssysteme. Kapitel 8. Kapitel 8. Folie: 1. Multiprozessorsysteme. Autor: Andrew S. Tanenbaum Moderne Betriebssysteme Kapitel 8 Multiprozessorsysteme Kapitel 8 Folie: 1 Multiprozessorsysteme Autor: Andrew S. Tanenbaum Pearson Studium 2009 2 3 4 5 6 7 Betriebssystemarten für Multiprozessoren Jede

Mehr

Klausur Informatik Programmierung, Seite 1 von 8 HS OWL, FB 7, Malte Wattenberg

Klausur Informatik Programmierung, Seite 1 von 8 HS OWL, FB 7, Malte Wattenberg Klausur Informatik Programmierung, 22.09.2011 Seite 1 von 8 Klausurteilnehmer Name: Matrikelnummer: Wichtige Hinweise Es sind keinerlei Hilfsmittel zugelassen auch keine Taschenrechner! Die Klausur dauert

Mehr

Modellierung und Programmierung 1

Modellierung und Programmierung 1 Modellierung und Programmierung 1 Prof. Dr. Sonja Prohaska Computational EvoDevo Group Institut für Informatik Universität Leipzig 19. November 2015 Gültigkeitsbereich (Scope) von Variablen { int m; {

Mehr

Klausurvorbereitung VS1 (Prof. Brecht) (B0rg Edition)

Klausurvorbereitung VS1 (Prof. Brecht) (B0rg Edition) Ein Prozess kann unmittelbar vom Zustand 1. Running in den Zustand Ready 2. Running in den Zustand Blocked 3. Ready in den Zustand Running Klausurvorbereitung VS1 (Prof. Brecht) (B0rg Edition) Der Adressraum

Mehr

= 7 (In Binärdarstellung: = 0111; Unterlauf) = -8 (In Binärdarstellung: = 1000; Überlauf)

= 7 (In Binärdarstellung: = 0111; Unterlauf) = -8 (In Binärdarstellung: = 1000; Überlauf) Musterlösung Übung 2 Aufgabe 1: Große Zahlen Das Ergebnis ist nicht immer richtig. Die Maschine erzeugt bei Zahlen, die zu groß sind um sie darstellen zu können einen Über- bzw. einen Unterlauf. Beispiele

Mehr

Funktionale Programmiersprachen

Funktionale Programmiersprachen Funktionale Programmiersprachen An den Beispielen Haskell und Erlang Übersicht Programmiersprachen λ-kalkül Syntax, Definitionen Besonderheiten von funktionalen Programmiersprache, bzw. Haskell Objektorientierte

Mehr

Technische Informatik II

Technische Informatik II Institut für Technische Informatik und Kommunikationsnetze Technische Informatik II Übung 1: Prozesse und Threads Aufgabe 1: Prozesse und Threads a) Wie verhält sich eine Applikation die aus mehreren Prozessen

Mehr

Informatik. Studiengang Chemische Technologie. Michael Roth WS 2012/2013. michael.roth@h-da.de. Hochschule Darmstadt -Fachbereich Informatik-

Informatik. Studiengang Chemische Technologie. Michael Roth WS 2012/2013. michael.roth@h-da.de. Hochschule Darmstadt -Fachbereich Informatik- Informatik Studiengang Chemische Technologie Michael Roth michael.roth@h-da.de Hochschule Darmstadt -Fachbereich Informatik- WS 2012/2013 Inhalt Teil VII Einstieg in Java I Michael Roth (h_da) Informatik

Mehr

PThreads. Pthreads. Jeder Hersteller hatte eine eigene Implementierung von Threads oder light weight processes

PThreads. Pthreads. Jeder Hersteller hatte eine eigene Implementierung von Threads oder light weight processes PThreads Prozesse und Threads Ein Unix-Prozess hat IDs (process,user,group) Umgebungsvariablen Verzeichnis Programmcode Register, Stack, Heap Dateideskriptoren, Signale message queues, pipes, shared memory

Mehr

Vorlesung "Verteilte Systeme" Sommersemester 1999. Verteilte Systeme. Adreßraum. Rechner. Verteilte Systeme, Sommersemester 1999 Folie 19.

Vorlesung Verteilte Systeme Sommersemester 1999. Verteilte Systeme. Adreßraum. Rechner. Verteilte Systeme, Sommersemester 1999 Folie 19. Verteilte Systeme 19. Distributed Shared Memory Sharing!! No Sharing! Sharing? Evolution der Berechnungsmodelle Vergangenheit Gemeinsamer Speicher Einzelrechner Gegenwart Nachrichtenkommunikation Verteilte

Mehr

Universität Karlsruhe (TH)

Universität Karlsruhe (TH) Universität Karlsruhe (TH) Forschungsuniversität gegründet 1825 OpenMP-Programmierung Teil II Multikern-Praktikum Wintersemester 06-07 Inhalt Was ist OpenMP? Parallele Regionen Konstrukte zur Arbeitsteilung

Mehr

C- Kurs 04 Anweisungen

C- Kurs 04 Anweisungen C- Kurs 04 Anweisungen Dipl.- Inf. Jörn Hoffmann jhoffmann@informa@k.uni- leipzig.de Universität Leipzig Ins@tut für Informa@k Technische Informa@k Ausdrücke Institut für Informatik Anweisungen C-Programm

Mehr

Domänenmodell: Fadenkommunikation und -synchronisation

Domänenmodell: Fadenkommunikation und -synchronisation Domänenmodell: Fadenkommunikation und -synchronisation Alexander Humphreys, Reinhard Rösch, Fabian Scheler 15. Mai 2003 Inhaltsverzeichnis 1 Domänendefinition 1 2 Domänenlexikon 1 3 Konzeptmodelle 4 4

Mehr

Übung zu Grundlagen der Betriebssysteme. 10. Übung 18.12.2012

Übung zu Grundlagen der Betriebssysteme. 10. Übung 18.12.2012 Übung zu Grundlagen der Betriebssysteme 10. Übung 18.12.2012 Aufgabe 1 a) Was versteht man unter einem kritischen Abschnitt oder kritischen Gebiet (critical area)? b) Welche Aufgabe hat ein Semaphor? c)

Mehr

SQL. SQL SELECT Anweisung SQL-SELECT SQL-SELECT

SQL. SQL SELECT Anweisung SQL-SELECT SQL-SELECT SQL SQL SELECT Anweisung Mit der SQL SELECT-Anweisung werden Datenwerte aus einer oder mehreren Tabellen einer Datenbank ausgewählt. Das Ergebnis der Auswahl ist erneut eine Tabelle, die sich dynamisch

Mehr

Algorithmen & Programmierung. Ausdrücke & Operatoren (1)

Algorithmen & Programmierung. Ausdrücke & Operatoren (1) Algorithmen & Programmierung Ausdrücke & Operatoren (1) Ausdrücke Was ist ein Ausdruck? Literal Variable Funktionsaufruf Ausdruck, der durch Anwendung eines einstelligen (unären) Operators auf einen Ausdruck

Mehr

Grundlagen der Programmentwicklung

Grundlagen der Programmentwicklung Informatik für Elektrotechnik und Informationstechnik Benedict Reuschling benedict.reuschling@h-da.de Hochschule Darmstadt Fachbereich Informatik WS 2013/14 Über C++ Über C++ C++ ist eine in der Industrie

Mehr

Parallel Processing in a Nutshell OpenMP & MPI kurz vorgestellt

Parallel Processing in a Nutshell OpenMP & MPI kurz vorgestellt Parallel Processing in a Nutshell & kurz vorgestellt 16. Juni 2009 1 / 29 1 Das Problem 2 2 / 29 1 Das Problem 2 3 2 / 29 1 Das Problem 2 3 4 2 / 29 1 Das Problem 2 3 4 2 / 29 Multi-Core Prozessoren halten

Mehr

Objektorientierte Programmierung OOP Programmieren mit Java

Objektorientierte Programmierung OOP Programmieren mit Java Objektorientierte Programmierung OOP Programmieren mit Java 5.1 Elementare Anweisungen 5.1.1 Ausdrucksanweisung 5.1.2 Leere Anweisung 5.1.3 Blockanweisung 5.1.4 Variablendeklaration 5.2 Bedingungen 5.2.1

Mehr

3 Variablen. 3.1 Allgemeines. 3.2 Definition und Verwendung von Variablen

3 Variablen. 3.1 Allgemeines. 3.2 Definition und Verwendung von Variablen 3 Variablen 3.1 Allgemeines Variablen werden in Prozeduren, Mustern und Parameter-Dokumenten definiert und verwendet und bei der Jobgenerierung durch die Werte, die ihnen zugewiesen werden, ersetzt. Variablen

Mehr

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = 0.51129 Euro ergeben.

Der Aufruf von DM_in_Euro 1.40 sollte die Ausgabe 1.40 DM = 0.51129 Euro ergeben. Aufgabe 1.30 : Schreibe ein Programm DM_in_Euro.java zur Umrechnung eines DM-Betrags in Euro unter Verwendung einer Konstanten für den Umrechnungsfaktor. Das Programm soll den DM-Betrag als Parameter verarbeiten.

Mehr

Informatik I Übung, Woche 40

Informatik I Übung, Woche 40 Giuseppe Accaputo 2. Oktober, 2014 Plan für heute 1. Fragen & Nachbesprechung Übung 2 2. Zusammenfassung der bisherigen Vorlesungsslides 3. Tipps zur Übung 3 Informatik 1 (D-BAUG) Giuseppe Accaputo 2 Nachbesprechung

Mehr

Universität Karlsruhe (TH)

Universität Karlsruhe (TH) Universität Karlsruhe (TH) Forschungsuniversität gegründet 1825 Das Java-Speichermodell Prof. Dr. Walter F. Tichy Dr. Victor Pankratius Ali Jannesari Geschichte des Speichermodells Kapitel 17 der Java-Sprachdefinition

Mehr

Microcontroller Praktikum SS2010 Dipl. Ing. R. Reisch

Microcontroller Praktikum SS2010 Dipl. Ing. R. Reisch Microcontroller Praktikum SS2010 Dipl. Ing. R. Reisch Die wichtigsten Unterlagen/Tools Für das Praktikum Unterlagen/Kenntnisse/Tools wichtig: Datenblatt des AT80USB1287 µc Schaltplan des im Praktikum verwendeten

Mehr