Shared-Memory Programmiermodelle

Ähnliche Dokumente
Besprechung Aufgabe 5 (crawl) POSIX-Threads. Problem: UNIX-Prozesskonzept ist für viele heutige Anwendungen unzureichend

Parallele Programmierung

RTEMS- Echtzeitbetriebssystem

fork () Hans-Georg Eßer, Hochschule München Betriebssysteme I, SS Prozesse (2/2) Folie 4

PROGRAMMIEREN MIT UNIX/Linux-SYSTEMAUFRUFEN

C allgemein. C wurde unter und für Unix entwickelt. Vorläufer sind BCPL und B.

Dämon-Prozesse ( deamon )

4. Parallelprogrammierung

Beispiel 3. Shared Memory und Explizite Synchronisation. Daniel Prokesch. 27. April Überblick. Shared Memory. Semaphore. Ressourcenverwaltung

Lab 13: Multi Processor Systems II

Übung zu Grundlagen der Betriebssysteme. 8. Übung

Musterlösung Prüfung SS 2002

Speicherbasierte Kommunikation (T) Realisierung von Semaphoren (T) Shared Memory (P) Synchronisation mittels Semaphoren (P)

Übung zu Grundlagen der Betriebssysteme. 7. Übung

Übersicht. Einführung in die Programmierung. main. main. main. main. Speicherverwaltung. Definition nach ANSI C:

Hochschule Ravensburg-Weingarten Schriftliche Prüfung Programmieren Prof. Dr. M. Zeller

2. Prozesssynchronisation

NEBEN - LÄUFIGE PROG RAM -

CS2101 Nebenläufige und Verteilte Programme Bachelor of Science (Informatik)

Embedded-Linux-Seminare. Linux als Betriebssystem

#define N 5 // Anzahl der Philosophen. while (TRUE) { // Der Philosoph denkt

Architektur paralleler Rechnersysteme - Effiziente HPC Systeme -

Programmieren in C. Macros, Funktionen und modulare Programmstruktur. Prof. Dr. Nikolaus Wulff

POSIX Echtzeit: Kernel 2.6 und Preempt-RT

Software Engineering für moderne, parallele Plattformen. 6. Parallelität in C/C++ Dr. Victor Pankratius. Dr. Victor Pankratius

Architektur paralleler Rechnersysteme - Effiziente HPC Systeme -

Einführung in die C-Programmierung

A Kompilieren des Kernels B Lineare Listen in Linux C Glossar Interessante WWW-Adressen Literaturverzeichnis...

Programmiersprachen Einführung in C. Unser erstes C-Programm. Unser erstes C-Programm. Unser erstes C-Programm. Unser erstes C-Programm

Dr. Monika Meiler. Inhalt

Lösung Übungszettel 6

II. Grundlagen der Programmierung. 9. Datenstrukturen. Daten zusammenfassen. In Java (Forts.): In Java:

2 Funktionen für die Verwaltung von Kontexten

Rechnerarchitektur und Betriebssysteme (CS201): Semaphor, Monitor, Deadlocks, Re-Entrance

Der Goopax Compiler GPU-Programmierung in C++ ZKI AK-Supercomputing, Münster, , Ingo Josopait

Prüfung VO Betriebssysteme SS2008 / 7. Juli 2008

1 Polymorphie (Vielgestaltigkeit)

Monitore. Klicken bearbeiten

Kapitel 2 Prozesse und Threads

Inhaltsverzeichnis. 2.4 Thread-Systeme. 2.1 Was ist ein Prozess? 2.2 Scheduling. 2.3 Interprozesskommunikation

Verteilte Systeme CS5001

Objektbasierte Entwicklung

Einführung Datentypen Verzweigung Schleifen Funktionen Dynamische Datenstrukturen. Java Crashkurs. Kim-Manuel Klein

2A Basistechniken: Weitere Aufgaben

b) Gegeben sei folgende Enumeration: enum SPRACHE {Deutsch, Englisch, Russisch};

Automatisierung ( Fernsteuerung ) von Excel unter Microsoft Windows Tilman Küpper (tilman.kuepper@hm.edu)

boost::asio-bibliothek 238

Das Monitorkonzept Brinch-Hansen

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

Arten der Synchronisation. Koordination nebenläufiger Prozesse. Koordinierung. Reihenschaltung. Einseitige Synchronisation

Betriebssystembau (BSB)

Systeme I: Betriebssysteme Kapitel 4 Prozesse. Maren Bennewitz

Architektur Verteilter Systeme Teil 2: Prozesse und Threads

Funktionen Häufig müssen bestimmte Operationen in einem Programm mehrmals ausgeführt werden. Schlechte Lösung: Gute Lösung:

Timm M. Steinbeck und Arne Wiebalck Lehrstuhl für Technische Informatik Universität Heidelberg. Prozess-Monitoring auf CPU-Takt Ebene

PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl

Betriebssysteme. 4y Springer. Eine kompakte Einführung mit Linux. Albrecht Achilles. Mit 31 Abbildungen

Betriebssysteme KU - Einführungstutorium

Klausur zur Vorlesung Grundlagen der Betriebssysteme WS 2011 / 2012

Übungspaket 31 Entwicklung eines einfachen Kellerspeiches (Stacks)

Rechnerorganisation Tutorium Nr. 1

Übung zu Grundlagen der Betriebssysteme. 3. Übung

Dienstspezifikation nach RFC

Interaktive Simulationen Lektion 1/3: Event-Driven Design und Signals

Organisatorisches. Einführung in die Programmierung in C Hochschule Regensburg Universitätsstraße 31, Regensburg

Betriebssysteme (BTS)

Architektur Verteilter Systeme Teil 6: Interprozess-Kommunikation

Betriebssysteme (BS)

Klausurvorbereitung VS1 (Prof. Brecht) (B0rg Edition)

Eine Einführung in C-Funktionen

Modellierung und Programmierung

^ Springer Vi eweg. Grundkurs Betriebssysteme. Synchronisation, Prozesskommunikation, Virtualisierung. Architekturen, Betriebsmittelverwaltung,

Ein- und Ausgabe von Paketen für Netzwerkverbindungen 208

Primitive Datentypen

Computergrundlagen Programmieren in C

Zum Abschluss wird gezeigt, wie aus einem C++ Quell-Programm ein ausführbares Programm erzeugt wird. 1. Installation von NetBeans...

Prozeß P1 Prozeß P2. Zur Synchronisation stehen den beiden Prozessen binäre Semaphore und die beiden Funktionen

MPI-Programmierung unter Windows mit MPICH2. Installieren von MPICH2, Übersetzen, Ausführen und Debuggen von MPI-Programmen. Christian Terboven

Softwarelösungen: Versuch 4

Deklarationen in C. Prof. Dr. Margarita Esponda

Proseminar Nichtsequentielle Programmiersprachen - alt und neu Einführung

Parallele Programmierung mit OpenMP

Einführung in die Programmierung Konstanten, dynamische Datenstrukturen. Arvid Terzibaschian

GUI Programmierung mit GTK

2. Programmierung in C

Inhaltsverzeichnis XII

Rechnernutzung in der Physik. Betriebssysteme

Systemprogrammierung unter UNIX System V / Linux

Einstieg in die Informatik mit Java

Steffen Heinzl Markus Mathes. Middleware in Java

Wiederholung: Semaphore (nicht gähnen!) Vorlesung Betriebssysteme II. Implementierung (Pseudocode) der P()-Operation.

Transkript:

Shared-Memory Programmiermodelle mehrere, unabhängige Programmsegmente greifen direkt auf gemeinsame Variablen ( shared variables ) zu Prozeßmodell gemäß fork/join Prinzip, z.b. in Unix: fork: Erzeugung eines neuen Kind-Prozesses (komplette Kopie des Elternprozesses zum Zeitpunkt der Erzeugung) wait: Elternprozess kann auf Terminierung der Kindprozesse warten Kommunikation der Prozesse über Signale, Sockets und ggf. auch über ein gemeinsames Speichersegment, das durch Systemfunktionen wie z.b. shmget, shmat, shmdet und shmop kontrolliert wird Threadmodell: mehrere unabhängige Kontrollflüsse in einem Programm bilden jeweils einen Thread Threads teilen sich einen globalen Adressraum Implementierung von Threads durch Bibliotheken, z.b. Pthreads (POSIX-Threads) für Unix 28 Shared-Memory Programmiermodelle (Forts.) Möglichkeiten der Implementierung eines Scheduling für Threads: 1) auf Anwender-Ebene: alle Anwender-Threads werden durch eine Bibliothek in einem Prozess realisiert; Vorteil: sehr schneller Thread- Wechsel ohne Beteiligung des Betriebssystems; Nachteil: kein Thread- Wechsel möglich, wenn ein Thread durch E/A-Operation blockiert ist 2) auf Betriebssystem-Ebene: jeder Anwender-Thread entspricht einem Kernel-Thread ( Leight-Weight Process, LWP); Vorteil: Zuordnung mehrerer Prozessoren zu Threads; Nachteil: nicht jedes Betriebssystem unterstützt Kernel-Threads! Beispiel: Linux Threads, Windows NT 3) auf Anwender- und Betriebssystem-Ebene: der Scheduler der Thread- Bibliothek bildet Anwender-Threads auf Betriebssystem-Threads ab; Scheduler des Betriebssystems bildet letztere ggf. auf Prozessoren ab Beispiel: Solaris 2 29

Thread-Programmierung Möglichkeiten der Arbeitsverteilung auf Threads: Master/Slave: ein Master-Thread steuert Programm, erzeugt mehrere Slave-Threads und verteilt Arbeit gleichmäßig auf Threads Pipelining: Thread i produziert Daten für Thread i +1 Pool: mehrere Threads holen sich nach Abarbeitung einer Aufgabe eine neue Aufgabe aus einem Aufgaben-Pool Divide-and-Conquer: jeder Thread erzeugt rekursiv einen weiteren Thread, bis Aufgabe ausreichend fein zerlegt ist Wettbewerb: jeder Thread führt eine andere Strategie aus jeder Thread hat Zugriff auf alle globalen Variablen und dynamisch erzeugte Objekte im globalen Adressraum, besitzt jedoch lokalen Laufzeitstack für private Variablen explizite Synchronisation beim Zugriff auf globale Variablen über Semaphore (Mutex-Variablen) 30 Posix Threads (Pthreads) ANSI/IEEE Standard (1995) zur betriebssystem-unabhängigen Thread-Programmierung das Thread-Scheduling ist jedoch betriebssystem-abhängig! Generierung eines Threads: int pthread_create (pthread_t *thread-id, const pthread_attr_t *attr, void *(*start_func) (void*), void *arg) mit thread-id : eindeutige Identifikation des erzeugten Threads attr : Datenstruktur, mit der einige Attribute des zu erzeugenden Threads festgelegt werden können, ansonsten NULL start_func : Name einer Startfunktion, die Thread nach Erzeugung ausführen soll arg : ein Parameter für Funktion start_func 31

Pthreads (Forts.) maximale Anzahl erzeugbarer Threads ist systemabhängig, jedoch mindestens 64 (gemäß POSIX-Standard) blockierendes Warten auf Beendigung eines Threads: int pthread_join (pthread_t thread-id, void **return_value) ein Thread kann seinen eigenen Bezeichner erfahren: pthread_t pthread_self(void) ein Thread terminiert bei Ende der in pthread_create angegebenen Startfunktion vorzeitig durch expliziten internen Aufruf der Funktion void pthread_exit (void *return_value) wenn er durch anderen Thread explizit abgebrochen wird: int pthread_cancel(pthread_t thread) wenn erzeugender Eltern-Thread terminiert 32 Pthreads Beispiel 1: Hello World #include <stdio.h> #define NUM_THREADS 5 void *PrintHello( void *id ) { printf( Hello World from Thread %d\n, id); pthread_exit( (void*) 0 ); main( int argc, char *argv[] ) { int status, t; pthread_t tids[num_threads]; for (t=0; t< NUM_THREADS, t++) { printf( Creating thread %d\n, t); if (pthread_create(&tids[t], NULL, PrintHello, (void*) t)!= 0){ printf( Error in pthread_create!\n"); exit(1); for (t=0; t< NUM_THREADS, t++) { if (pthread_join(tids[t], (void**)&status)!= 0) { printf( Error in pthread_join!\n"); exit(1); if (status == 0) printf( Thread %d terminated correctly.\n, t); 33

Pthreads Beispiel 2: Matrix-Multiplikation double X[DIM][DIM], M[DIM][DIM], Y[DIM][DIM]; typedef struct {int row; int col; work_t; void* matmult(void* arg) { int i; work_t *work = (work_t*) arg; Y[work->row][work->col]=0; for (i=0; i < DIM; i++) Y[work->row][work->col] += X[work->row][i] * M[i][work->col]; int main( int argc, char *argv[] ) { int i,j; work_t work[dim][dim]; pthread_t tid[dim][dim]; for (i=0; i < DIM; i++) for (j=0; j < DIM; j++) { work[i][j].row = i; work[i][j].col = j; pthread_create(&tid[i][j], NULL, matmult,(void*) &work[i][j]); for (i=0; i < DIM; i++) for (j=0; j < DIM; j++) pthread_join(tid[i][j], NULL); 34 Pthreads (Forts.) Koordination von Threads durch Mutex-Variablen: Deklaration einer Mutex-Variablen für einen gegenseitigen Ausschluß pthread_mutex_t *mutex Initialisierung einer Mutex-Variablen (Default mit attr=null) int pthread_mutex_init (pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) Thread, der zuerst eine gemeinsame Datenstruktur modifizieren möchte, sperrt zuvor die zugehörige Mutex-Variable int pthread_mutex_lock (pthread_mutex_t *mutex) ruft ein anderer Thread diese Funktion mit der gleichen Mutex-Variablen auf, so wird er blockiert, bis Mutex-Variable wieder frei ist nach Beendigung des Zugriffs gibt Thread die zugehörige Mutex- Variable wieder frei: int pthread_mutex_unlock (pthread_mutex_t *mutex) Test, ob Mutex-Variable bereits durch einen anderen Thread belegt ist: int pthread_mutex_trylock (pthread_mutex_t *mutex) 35

Pthreads Beispiel 3: Skalarprodukt #define NUMTHRDS 4 #define VECLEN 100000 double a[veclen]; double b[veclen]; double sum; pthread_mutex_t mutexsum; /* already initialized in main */ void *dotprod(void *tid) { int i, len, start, end; double mysum = 0; len = VECLEN / NUMTHRDS; start = (int) tid * len; end = start + len; for (i=start; i<end ; i++) /* compute local part of dot product */ mysum += (a[i] * b[i]); pthread_mutex_lock (&mutexsum); sum += mysum; /* critical region */ pthread_mutex_unlock (&mutexsum); pthread_exit((void*) 0); 36 Pthreads (Forts.) Koordination von Threads durch Bedingungsvariablen: Deklaration einer Bedingungsvariablen: pthread_cond_t *cond Initialisierung einer Bedingungs-Variablen (Default mit attr=null): int pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *attr) Thread wird blockiert, bis die zu cond gehörende Bedingung eintritt: int pthread_cond_wait (pthread_cont_t *cond, pthread_mutex_t *mutex) jede Bedingungsvariable ist mit einer Mutex-Variable assoziiert: vor pthread_cond_wait muss daher pthread_mutex_lock(mutex) aufgerufen werden; während einer Blockierung ist mutex jedoch frei! Sobald Bedingung in einem anderen Thread erfüllt ist, kann dieser einen oder alle bzgl. der Variablen cond blockierten Threads aufwecken: int pthread_cond_signal (pthread_cond_t *cond) int pthread_cond_broadcast (pthread_cond_t *cond) 37

Pthreads Beispiel 4: Thread-Pool #define NUM_THREADS 10 #define MAX_TASKS 100 typedef struct { pthread_mutex_t lock; pthread_cond_t empty, not_full; /*... further variables for task queue ( not shown here )... */ work_t; void main() { int i; work_t *work; pthread_t tids[num_threads]; pthread_mutex_init(work->lock); pthread_cond_init(work->empty); pthread_cond_init(work->not_full); for (i=0; i < NUM_THREADS; i++) { pthread_create(&tids[i], NULL, (void*) worker, (void*) work); 38 Pthreads Beispiel 4: Thread-Pool (Forts.) void worker(work_t *work) { while (TRUE) { pthread_mutex_lock(work->lock); while (work->num_of_tasks == 0) pthread_cond_wait(work->not_empty, work->lock); /*... get next job from task queue ( not shown here )... */ if (work->num_of_tasks == MAX_TASKS) pthread_cond_broadcast(work->not_full); work->num_of_tasks--; pthread_mutex_unlock(work->lock); /*... start next job from task queue ( not shown here )... */ void insert_job (work_t *work) { pthread_mutex_lock(work->lock); while (work->num_of_tasks == MAX_TASKS) pthread_cond_wait(work->not_full, work->lock); if (work->num_of_tasks == 0) pthread_cond_signal(work->not_empty); /*... put job in task queue ( not shown here )... */ work->num_of_tasks++; pthread_mutex_unlock(work->lock); 39