5. PThreads Thread-basierte. Programmierung von Multicore-Systemen

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

Shared-Memory Programmiermodelle

Threads Einführung. Zustände von Threads

Tafelübung zu BS 2. Threadsynchronisation

Tafelübung zu BS 2. Threadsynchronisation

Rechnerarchitektur SS 2012

Tafelübung zu BS 2. Threadsynchronisation

Softwaresysteme I Übungen Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2007 U9.fm

POSIX-Threads. Aufgabe 9 SP - Ü U10.1

U9-3 Vergleich von Thread-Konzepten. U9-2 Motivation von Threads. U9-3 Vergleich von Thread-Konzepten (2) U9-1 Überblick

U8 POSIX-Threads U8 POSIX-Threads

Threads. Foliensatz 8: Threads Folie 1. Hans-Georg Eßer, TH Nürnberg Systemprogrammierung, Sommersemester 2015

Rechnerarchitektur SoSe TU Dortmund

I 7. Übung. I-1 Überblick. Besprechung Aufgabe 5 (mysh) Online-Evaluation. Posix Threads. Ü SoS I I.1

U8-1 Motivation von Threads. U8-2 Vergleich von Thread-Konzepten. U8-2 Vergleich von Thread-Konzepten (2) Motivation

Besprechung Aufgabe 1: Prozesse verwalten Fortsetzung Grundlagen C-Programmierung Aufgabe 2: Threadsynchronisation

Betriebssysteme. Tafelübung 2. Thread-Synchronisation. Olaf Spinczyk.

Concurrency and Processes of Pthreads

Rechnerarchitektur SS 2012

Aufgabe 9: recgrep rekursive, parallele Suche (letzte Aufgabe)

Aufgabenblatt 6 Musterlösung

Multithread Programming

Vorlesung Betriebssysteme I

Aufgabenblatt 5 Musterlösung

Operating Systems Principles. Eventund. Threadbasierte Programmierung

Einführung in POSIX Threads

Markus Klußmann, Amjad Saadeh Institut für Informatik. Pthreads. von Markus Klußmann und Amjad Saadeh. Pthreads

POSIX Solaris thread management pthread_create thr_create pthread_exit thr_exit pthread_kill thr_kill pthread_self thr_self

Linux Prinzipien und Programmierung

User-Level-Threads (Koroutinen) Realisierung von Threads auf Benutzerebene innerhalb eines Prozesses

Inhalt. Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Motivation

Parallele Programmierung

Pthreads. David Klaftenegger. Seminar: Multicore Programmierung Sommersemester

Übungen zu Systemnahe Programmierung in C (SPiC)

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

Übungen zu Systemnahe Programmierung in C (SPiC) Inhalt. Sebastian Maier (Lehrstuhl Informatik 4) Übung 10. Sommersemester 2016

Übungen zu Systemnahe Programmierung in C (SPiC) Sommersemester 2018

Echtzeitbetriebssysteme (am Beispiel QNX) Dr. Stefan Enderle HS Esslingen

Übungen zu Systemprogrammierung 1 (SP1)

Übungen zu Systemprogrammierung 1

Übungen zu Systemprogrammierung 1 (SP1)

Homogene Multi-Core-Prozessor-Architekturen

Prozesse und Threads. wissen leben WWU Münster

C-Kurs 2010 Pointer. 16. September v2.7.3

Aufgabe 6: palim rekursive, parallele Suche nach einer Zeichenkette

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

Beispiel: Schleifenparallelisierung

Programmierung von Parallelrechnern

long global_cnt; /* global counter */ time_t s_time, e_time; /* start/end time of counting */ clock_t CPU_time; /* used CPU time for counting */

Threads. Netzwerk - Programmierung. Alexander Sczyrba Jan Krüger

Einführung in POSIX-Threads. WS 08/09 Universität Innsbruck

Lehrstuhl für Datenverarbeitung. Technische Universität München. Leistungskurs C++ Multithreading

Linux. Dipl.-Inf., Dipl.-Ing. (FH) Michael Wilhelm. FB Automatisierung und Informatik.

Linux. Dipl.-Inf., Dipl.-Ing. (FH) Michael Wilhelm. Hochschule Harz. FB Automatisierung und Informatik.

Lehrstuhl für Datenverarbeitung. Technische Universität München. Leistungskurs C++ Multithreading

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

Leseprobe. Kapitel 12:»Threads« Inhaltsverzeichnis. Index. Die Autoren. Leseprobe weiterempfehlen.

Architecture of Parallel Computer Systems - Efficient HPC Systems -

Einleitung Entwicklung in C Hello-World! Konstrukte in C Zusammenfassung Literatur. Grundlagen von C. Jonas Gresens

System-Makro in time.h : #define CLOCKS_PER_SEC 1000 Frühere Makro-Bezeichnung (z.t. noch gebräuchlich): #define CLK_TCK CLOCKS_PER_SEC//aus:time.

Variablen. Deklaration: «Datentyp» «Variablenname» Datentyp bestimmt Größe in Bytes: sizeof Beispiel: long int v; Größe: 4 Bytes

Thread-Synchronisation in in Java. Threads Wechselseitiger Ausschluss Bedingte Synchronisation Beispiel: Warteschlangen

Übungen zu Systemprogrammierung 1 (SP1)

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

Programmierung von. Parallelrechnern. Speicher WS 1995/96. Heinz Kredel, Akitoshi Yoshida. Rechenzentrum Universitat Mannheim RUM 46/96

C-Crashkurs. Praktikum Systemmanagement und Sicherheit

Inhaltsverzeichnis. Carsten Vogt. Nebenläufige Programmierung. Ein Arbeitsbuch mit UNIX/Linux und Java ISBN:

U6-1 Organisatories. U6-2 Motivation von Threads. U6-3 Vergleich von Thread-Konzepten. Organisatorisches

Architecture of Parallel Computer Systems - HPC Architecture -

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Systemprogrammierung Unix/Linux SS 2013 Hans-Georg Eßer, Ohm-Hochschule Nürnberg Übung 13 3/

Pthreads. David Klaftenegger. Seminar: Multicore Programmierung Sommersemester

C/C++-Programmierung

G 5. Übung. G-1 Überblick. Besprechung 3. Aufgabe. Infos zur Aufgabe 5: fork, exec. Rechenzeiterfassung. Ü SoS I G.1

Syntax und Kontrollstrukturen

Architektur paralleler Rechnersysteme - Effiziente HPC Systeme -

Alle Fäden in der Hand

Nebenläufige und Verteilte Programme. Thomas Letschert

C++ atomics, Boost.Lookfree, Hazard-Pointers und die Thread-Hölle

Angewandte Mathematik und Programmierung

Grundlagen der Informatik III Wintersemester 2010/2011

TI III: Operating and Communication. WS 2008/09 Übungsblatt Nr. 1

6. Der OpenMP Standard. Direktiven-basiertes API zur Programmierung von Parallelrechnern mit gemeinsamem Speicher für FORTRAN, C und C++

C-Kurs 2011: Arrays, Strings, Pointer

Architektur paralleler Rechnersysteme - Effiziente HPC Systeme -

C++ Teil 7. Sven Groß. 30. Nov Sven Groß (IGPM, RWTH Aachen) C++ Teil Nov / 13

Systempraktikum im Wintersemester 2009/2010 (LMU): Vorlesung vom Foliensatz 2

Einführung in C. Alexander Batoulis. 5. Mai Fakutltät IV Technische Universität Berlin

Verwendung Vereinbarung Wert einer Funktion Aufruf einer Funktion Parameter Rekursion. Programmieren in C

2A Basistechniken: Lösungen 2A.1 Wissens- und Verständnisfragen

Best Practices. Rainer Grimm Training, Coaching und Technologieberatung

Entfernungsmesser. für den Raspberry Pi. Tim Riddermann / Nils Wortmann

Kontrollfragen Mikrocontroller Programmiersprache C H1203 Felix Rohrer

Organisatorisches. Übungsleiter: Karsten Otto Homepage: Aufgaben

Transkript:

5. PThreads Thread-basierte Programmierung von Multicore-Systemen

Pthreads: : POSIX Thread API Standard Thread API IEEE POSIX 1003.1c standard #include <pthread.h> 3 Klassen von Routinen Threadverwaltung Erzeugung, Termination, Synchronisation, Setzen und Abfragen von Attributwerten Wechselseitiger Ausschluss (mutexes) Erzeugung, Löschen, Sperren und Entsperren von Mutexvariablen; Setzen und Modifikation von Mutex.-Attributen Bedingungsvariablen Erzeugung, Entfernen, Warten und Signalisieren auf Bedingungsvariablen, Setzen/Abfragen von Attributwerten 216

Namenskonventionen Alle Bezeichner beginnen mit pthread_. Präfix pthread_ pthread_attr_ pthread_mutex_ pthread_mutexattr_ pthread_cond_ pthread_condattr_ Funktionale Gruppe Threads selbst und Routinen Thread Attributobjekte Mutexes Mutex Attributobjekte Bedingungsvariablen Attributobjekte zu Bedingungsvariablen Compilation von Programmen mit gcc -pthread 217

Threadverwaltung Thread-Erzeugung int pthread_create ( pthread_t *thread_handle, const pthread_attr_t *attribute, void * (*thread_function){void *, void *arg); Thread-Synchronisation int pthread_join ( pthread_t thread, void **ptr); Thread-Termination Thread beendet Ausführung Aufruf von pthread_exit() Annulierung durch anderen Prozess mittels pthread_cancel Prozess terminiert 218

Beispiel: Hello World #include <pthread.h> #include <stdio.h> #define NUM_THREADS 5 void *PrintHello(void *threadid) { int tid; tid = (int)threadid; printf("hello World! It's me, thread #%d!\n", tid); pthread_exit(null); int main (int argc, char *argv[]) { pthread_t threads[num_threads]; int rc, t; for(t=0; t<num_threads; t++){ printf("in main: creating thread %d\n", t); rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t); if (rc){ printf("error; return code from pthread_create() is %d\n", rc); exit(-1); pthread_exit(null); 219

Argumentübergabe Weitergabe eines Arguments an die Start-Routine eines Threads call-by-reference Übergabe mit einem cast zu (void *) int *taskids[num_threads];... for(t=0;t<num_threads;t++) { taskids[t] = (int *) malloc(sizeof(int)); *taskids[t] = t; printf("creating thread %d\n", t); rc = pthread_create(&threads[t], NULL, PrintHello, (void *) taskids[t]);... Mehrere Argumente müssen in einer Struktur zusammengefasst werden. 220

Beispiel: Übergabe mehrerer Argumente struct thread_data { int thread_id; int sum; char *message; ; struct thread_data thread_data_array[num_threads]; void *PrintHello(void *threadarg) {...; struct thread_data *my_data; my_data = (struct thread_data *) threadarg; taskid = my_data->thread_id; sum = my_data->sum; hello_msg = my_data->message;... int main(int argc, char *argv[]) {... thread_data_array[t].thread_id = t; thread_data_array[t].sum = sum; thread_data_array[t].message = messages[t]; rc = pthread_create(&threads[t], NULL, PrintHello, (void *) &thread_data_array[t]);... 221

Beispiel: Thread Synchronisation Das Attributargument von pthread_create () wird genutzt, um einen Thread als joinable oder detached (nicht joinable) zu erzeugen. typischer Ablauf: pthread_attr_t attr; /* Deklaration */... pthread_attr_init(&attr); /* Initialisierung */ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); /* Status joinable sicherstellen */... rc = pthread_create(&thread[t], &attr, BusyWork, NULL);... pthread_attr_destroy(&attr);... rc = pthread_join(thread[t], &status); => Programm: join1.c 222

Fallstudie: Berechnung von pi #include <pthread.h> #include <stdlib.h>... #define MAX_THREADS 512 void *compute_pi (void *);... main() {... pthread_t p_threads[max_threads]; pthread_attr_t attr;... pthread_attr_init (&attr);... for (i=0; i< num_threads; i++) { hits[i][0] = i; pthread_create( &p_threads[i], &attr, compute_pi, (void *) &hits[i][0]); for (i=0; i< num_threads; i++) { pthread_join( p_threads[i], NULL); total_hits += hits[i][0];... 223

Beispiel: Berechnung von pi (Forts.) void *compute_pi (void *s) { int thread_no, i, *hit_pointer; double rand_no_x, rand_no_y; int hits; hit_pointer = (int *) s; thread_no = *hit_pointer; hits = 0; srand48(thread_no); for (i = 0; i < sample_points_per_thread; i++) { rand_no_x = (double)(rand_r(&thread_no))/(double)((2 <<30) - 1); rand_no_y = (double)(rand_r(&thread_no))/(double)((2 <<30) - 1); if (((rand_no_x - 0.5) * (rand_no_x - 0.5) + (rand_no_y - 0.5) * (rand_no_y - 0.5)) < 0.25) (*hit_pointer) ++; hits ++; *hit_pointer = hits; 224

Wechselseitiger Ausschluss mittels binärer Semaphor-Variablen: mutex-locks Sperren int pthread_mutex_lock ( pthread_mutex_t *mutex_lock); Entsperren int pthread_mutex_unlock ( pthread_mutex_t *mutex_lock); Initialisieren int pthread_mutex_init ( pthread_mutex_t *mutex_lock, const pthread_mutexattr_t *lock_attr); 225

Beispielanwendung pthread_mutex_t minimum_value_lock;... main() {... pthread_mutex_init(&minimum_value_lock, NULL);... void *find_min(void *list_ptr) {... pthread_mutex_lock(&minimum_value_lock); if (my_min < minimum_value) minimum_value = my_min; pthread_mutex_unlock(&minimum_value_lock); => Programme dotprod_serial.c, dotprod_mutex.c 226

Verringerung des Locking-Overheads pthread_mutex_trylock als Alternative zu pthread_mutex_lock pthread_mutex_trylock. int pthread_mutex_trylock ( pthread_mutex_t *mutex_lock); keine Blockade, sondern Rückgabe von EBUSY schneller, da keine Warteschlangenverwaltung 227

Beispiel: k Kopien eines Elementes finden void *find_entries(void *start_pointer) { struct database_record *next_record; int count; current_pointer = start_pointer; do { next_record = find_next_entry(current_pointer); count = output_record(next_record); while (count < requested_number_of_records); int output_record(struct database_record *record_ptr) { int count; pthread_mutex_lock(&output_count_lock); output_count ++; count = output_count; pthread_mutex_unlock(&output_count_lock); if (count <= requested_number_of_records) print_record(record_ptr); return (count); 228

Beispiel:... mit trylock int output_record(struct database_record *record_ptr) { int count; int lock_status; lock_status=pthread_mutex_trylock(&output_count_lock); if (lock_status == EBUSY) { insert_into_local_list(record_ptr); return(0); else { count = output_count; output_count += number_on_local_list + 1; pthread_mutex_unlock(&output_count_lock); print_records(record_ptr, local_list, requested_number_of_records - count); return(count + number_on_local_list + 1); 229

Bedingungsvariablen zur einseitigen Synchronisation immer mit mutex-lock assoziiert Funktionen int pthread_cond_wait( pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_signal(pthread_cond_t *cond); int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_init( pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_destroy(pthread_cond_t *cond); 230

Beispiel: Producer-Consumer pthread_cond_t cond_queue_empty, cond_queue_full; pthread_mutex_t task_queue_cond_lock; int task_available; /* other data structures here */ main() { /* declarations and initializations */ task_available = 0; pthread_cond_init(&cond_queue_empty, NULL); pthread_cond_init(&cond_queue_full, NULL); pthread_mutex_init(&task_queue_cond_lock, NULL); /* create and join producer and consumer threads */ 231

Beispiel (Forts.): Producer void *producer(void *producer_thread_data) { int inserted; while (!done()) { create_task(); pthread_mutex_lock(&task_queue_cond_lock); while (task_available == 1) pthread_cond_wait(&cond_queue_empty, &task_queue_cond_lock); insert_into_queue(); task_available = 1; pthread_cond_signal(&cond_queue_full); pthread_mutex_unlock(&task_queue_cond_lock); 232

Beispiel (Forts.): Consumer void *consumer(void *consumer_thread_data) { while (!done()) { pthread_mutex_lock(&task_queue_cond_lock); while (task_available == 0) pthread_cond_wait(&cond_queue_full, &task_queue_cond_lock); my_task = extract_from_queue(); task_available = 0; pthread_cond_signal(&cond_queue_empty); pthread_mutex_unlock(&task_queue_cond_lock); process_task(my_task); 233

Fallstudie: Lese-/Schreibsperren (read( read/write locks) erweiterter Synchronisationsmechanismus vgl. Leser-/Schreiber-Problem realisierbar mit mutex- und Bedingungsvariablen Beispielrealisierung einer RW-Sperrvariablen vom Typ mylib_rwlock_t typedef struct { Zähler readers für Leser int readers; Zähler writer für int writer; Schreiber (ist 0 oder 1) pthread_cond_t readers_proceed; 2 Bedingungsvariablen pthread_cond_t writer_proceed; readers_proceed int pending_writers; writer_proceed pthread_mutex_t read_write_lock; Zähler pending_writers mylib_rwlock_t; wartender Schreiber Mutex-Variable read_write_lock zum Schutz des Datenbereichs 234

Initialisierung void mylib_rwlock_init (mylib_rwlock_t *l) { l->readers = l->writer = l->pending_writers = 0; pthread_mutex_init( &(l->read_write_lock), NULL); pthread_cond_init( &(l->readers_proceed), NULL); pthread_cond_init( &(l->writer_proceed), NULL); Funktionen mylib_rwlock_rlock mylib_rwlock_wlock mylib_rwlock_unlock - Leserzugang -Schreiberzugang -Freigabe 235

Leserzugang void mylib_rwlock_rlock(mylib_rwlock_t *l) { /* if there is a write lock or pending writers, perform condition wait.. else increment count of readers and grant read lock */ pthread_mutex_lock(&(l->read_write_lock)); while ( (l->pending_writers > 0) (l->writer > 0)) pthread_cond_wait(&(l->readers_proceed), &(l->read_write_lock)); l -> readers ++; pthread_mutex_unlock(&(l->read_write_lock)); 236

Schreiberzugang void mylib_rwlock_wlock(mylib_rwlock_t *l) { /* if there are readers or writers, increment pending writers count and wait. On being woken, decrement pending writers count and increment writer count */ pthread_mutex_lock(&(l->read_write_lock)); while ((l->writer > 0) (l->readers > 0)) { l -> pending_writers ++; pthread_cond_wait(&(l->writer_proceed), &(l->read_write_lock)); l->pending_writers--; l -> writer++; pthread_mutex_unlock(&(l->read_write_lock)); 237

Freigabe void mylib_rwlock_unlock(mylib_rwlock_t *l) { /* if there is a write lock then unlock, else if there are read locks, decrement count of read locks. If the count is 0 and there is a pending writer, let it through, else if there are pending readers, let them all go through */ pthread_mutex_lock(&(l->read_write_lock)); if (l->writer > 0) l->writer = 0; else if (l->readers > 0) l->readers--; if ((l->readers == 0) && (l->pending_writers > 0)) pthread_cond_signal(&(l->writer_proceed)); else if (l->readers > 0) pthread_cond_broadcast(&(l->readers_proceed)); pthread_mutex_unlock(&(l->read_write_lock)); 238

Fallstudie: Lineare Barriere typedef struct { pthread_mutex_t pthread_cond_t int count; mylib_barrier_t; count_lock; ok_to_proceed; void mylib_init_barrier(mylib_barrier_t *b) { b -> count = 0; pthread_mutex_init( &(b -> count_lock), NULL); pthread_cond_init( &(b -> ok_to_proceed), NULL); 239

void mylib_barrier (mylib_barrier_t *b, int num_threads) { pthread_mutex_lock(&(b -> count_lock)); b -> count ++; if (b->count == num_threads) { b->count = 0; pthread_cond_broadcast(&(b->ok_to_proceed)); else while (pthread_cond_wait( &(b->ok_to_proceed), &(b->count_lock))!= 0); pthread_mutex_unlock(&(b -> count_lock)); 240