Shared Memory Programming Pthreads: DR Matthew Grove Slides
Shared Memory Programming Pthreads: DR Matthew Grove Slides
Lecture Goals
! Shared memory, threads and processes ! Basic Pthreads ! Thread safety
!Race conditions !Critical sections !Locks
Techniques
! Heavyweight processes. ! Threads. Example Pthreads, Java threads. ! New programming language for parallel programming - not popular. Example Ada. ! Modifying the syntax of an existing sequential programming language to create a parallel programming language. Example UPC. ! Using an existing sequential programming language supplemented with compiler directives and libraries for specifying parallelism. Example OpenMP.
August 24, 2011
Heavyweight Processes
! Operating systems are often based upon the notion of a process. ! Processor time is shared between processes, switching from one process to another. This might occur at regular intervals or when an active process becomes delayed. ! Concept can be used for parallel programming. Not much used because of overhead. Threads are preferred.
Threads vs Processes
Thread Summary
! Exists within a process and uses the process resources. ! Has own independent ow of control as long as its parent process exists and the OS supports it. ! Duplicates only the essential resources it needs to be independently schedulable. ! May share the process resources with other threads that act equally independently. ! Dies if the parent process dies. ! Is "lightweight" because most of the overhead of creating the thread occurs when the process starts.
August 24, 2011
Source: https://computing.llnl.gov/tutorials/pthreads/fork_vs_thread.txt
August 24, 2011
Memory Bandwidth
Source: https://computing.llnl.gov/tutorials/pthreads/
August 24, 2011
Pthreads
! Historically vendors provided their own thread libraries. ! The adopted standard for Unix was created by the IEEE and called POSIX 1003.1c (1995). ! Any implementation of this standard is referred to as POSiX Threads or Pthreads.
Detached Threads
Exiting a Thread
! The thread will exit naturally after the thread start routine returns. ! Thread itself calls pthread_exit. ! Another thread calls pthread_cancel. ! The process itself exits.
Execution Order
! On a single processor a thread will typically execute until it is blocked. ! For multi-processor the threads execution can be interleaved in time. ! Unless you are guaranteeing execution order then you can not assume anything about it.
Interleaved Execution
! Consider two threads which print sentences to the terminal. ! The characters being printed will also be interleaved making garbled sentences print to the screen. ! T0: -> The weather is nice. ! T1: -> I am going to the shops. ! Output: Th I e wam geatheoing to thr ie shs nice. ops.
August 24, 2011
Race Conditions
Critical Sections
! Critical sections provide a way to make sure only one process accesses a resource at a time. ! The critical section is the code that accesses the resource. They must be arranged such that only one section can be executed at a time. ! This mechanism is known as mutual exclusion.
Locks
! A lock is the simplest mechanism for ensuring mutual exclusion of critical sections. ! It can only have two values: ! 1 - a process has entered the critical section. ! 0 - there is no process in the critical section. ! To enter the critical section you must acquire the lock. ! On leaving the critical section you release the lock. This is done by changing the value back to 0.
! A thread will wait until it can acquire the lock. If multiple threads are waiting, only one will be picked to receive the lock when the lock is available. Only one thread will ever be able to acquire the lock. Only the thread that locked the mutex can unlock it.
August 24, 2011
Serialization Example
Deadlock
! Deadlock can occur when two processes both require a resource currently held by the other.
Circular Deadlock
! Deadlock can also occur in a circular fashion with several holding a resource required by another.
! This method will return an EBUSY status if the mutex is currently locked. If the mutex is not locked it will lock it. This might help overcome a deadlock situation but it is still requires careful code design.
General Semaphores
! Pthread primitives can be used to create more complex routines. ! The general semaphore (or counting semaphore) can store an integer in a thread safe way. ! Can be used to track available resources such as work available in a queue. ! Available in thread libraries for languages such as Java but do not exist in vanilla Pthreads. ! You can however write your own using the Pthread methods.
August 24, 2011
Condition Variables
! Often a decision about when to execute a critical section is made using some kind of global condition. ! For example if a total has reached a certain point. ! This could be achieved by locking and unlocking a variable in order to check it. This kind of polling is very costly. ! Condition variables o!er a solution.
Condition Variables
! Thread 1: ! Lock mutex and check value of a global variable. ! Call pthread_cond_wait() to perform a blocking wait for a signal. pthread_cond_wait() automatically unlocks the associated mutex variable. ! Thread 2: ! Lock mutex. ! Change global counter. ! If counter has reached the value needed by thread 1 it calls pthread_cond_signal(). ! Unlock the mutex. ! Thread 1: ! Wake up when received signal. ! Mutex is automatically locked again.
August 24, 2011
Condition Variables
Thread 1 Thread 2
Monitor Methods
! A programming technique for providing thread safety. ! Wrap shared resources in an access procedure which uses some kind of lock to prevent concurrent calls by multiple threads.
monitor_update_foo(var){ lock(c); ... //Update foo here ... unlock(c); } August 24, 2011 ! !
Tuesday, September 13, 2011
Race Example
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #define NTHREADS 100 #define LOOPS 10000 int sum = 0; pthread_mutex_t sum_mutex; void *do_work() { int i; pthread_mutex_lock(&sum_mutex); for (i=0; i<LOOPS; i++) sum = sum + 1; pthread_mutex_unlock(&sum_mutex); pthread_exit(NULL); } ...
...
int main(int argc, char *argv[]) { int i; pthread_t threads[NTHREADS]; pthread_attr_t attr; pthread_mutex_init(&sum_mutex, NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); for (i=0; i<NTHREADS; i++) pthread_create(&threads[i], &attr, &do_work, NULL); for (i=0; i<NTHREADS; i++) pthread_join(threads[i], NULL); printf("Thread sum: %d\n", sum); sum=0; for (i=0;i<NTHREADS * LOOPS;i++) sum = sum + 1; printf("Check sum: %d\n",sum); pthread_attr_destroy(&attr); pthread_mutex_destroy(&sum_mutex); pthread_exit(NULL);
August 24, 2011
Demo
! ...
Homework
! Compile hello world for Pthreads. ! Assign each thread a unique number and make it print the number. ! Synchronize the threads such that they always print their number in ascending order.
I am I am I am I am ... thread thread thread thread 0 1 2 3