Professional Documents
Culture Documents
Table of contents
Basics
Processes & threads
Posix threads
Managing threads
Mutually exclusive threads
Threads
Smallest unit of processing
that a scheduler work on.
Threads executing under
the same process share
the address space
They are light-weighted i.e.
easy to create
Context switching between
threads is very fast.
Programming model
Linux processes
A process on a Linux system is an object through which
the resources used by a program like memory, processor
time and IO are managed and monitored.
Processes are building blocks of any Linux system and
can run in the kernel space or in the user space.
A process consists of an address space
(a set of memory pages) and a set of data structures.
The address space of a process contains the code and
libraries that the process is executing,the process
variables, its stacks, and various extra information needed
by the kernel while the process is running.
Some of the common Linux command to monitor and
manage processes are ps -ef, top, strace, kill etc.
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 8
Try of a definition
A thread is a sequence of related instructions executed
independently of other instruction sequences
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 9
Multi threads
If we run multiple threads concurrently,
we are doing multi-threading i.e. we run
several tasks in parallel
In a multi-thread process the processor
can switch execution resources
between threads, resulting in
concurrent execution.
Concurrency on a single processor (core) system
indicates that more than one thread is making progress,
but the threads are not actually running simultaneously.
On a multi-core system each thread in the process can
run concurrently on a separate core i.e., true parallelism.
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 11
Managing pthreads
To create a new thread, a running thread calls the
pthread_create() function, and passes a pointer to a
function for the new thread to run.
One argument for the new threads function can also be
passed, along with thread attributes.
The execution of a thread begins with the successful
return from the pthread create() function.
The thread ends when the function that was called with
the thread completes normally.
A thread can also be terminated if the thread calls a
pthread_exit() routine, or if any other thread calls
pthread_cancel() to explicitly terminate that thread.
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 13
// EXAMPEL pthread : create & join Shows how data can be returned by a subprogram
#include <stdio.h>
#include <pthread.h>
void print_char (void ch){
int i ;
for ( i =0; i <10; i ++)
printf ( "%c", (char)ch);
return NULL; }
int main ()
{
char ch1=, ch2=;
pthread_t p1, p2;
pthread_create (&p1, NULL, print_char, &ch1);
pthread_create (&p2, NULL, print_char, &ch2);
pthread_join (p1, NULL);
pthread_join (p2, NULL);
printf ( " \n") ;
return 0;
}
Compile with
pthread_create
int pthread_create (pthread_t *th, pthread_attr_t *attr,void *(*start_routine)(void*),void *arg);
/
EXAMPEL pthread : return
This programs shows how data can be returned by a subprogram
which every threads exectute in parallel .
/
#include <pthread.h>
#include <stdio.h>
#include<stdlib .h>
void child_thread( void param ){
long id , jd ;
id = (long )param;
jd = id id;
return (void )jd ;
}
int main(int argc, char argv[]) {
long i ;
pthread_t thread;
long return_value;
int num_threads;
Listing 1: pt_return.c
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 17
<# threads>\n");
num_threads = atoi(argv[1]);
thread = (pthread_t )malloc(num_threadssizeof(pthread_t));
return_value=(long )malloc(num_threadssizeof(long ));
for ( i =0; i <num_threads; i++ ){
pthread_create(&thread[i],NULL,&child_thread,(void)i );
}
for ( i =0; i <num_threads ; i++ ) {
pthread_join(thread[ i ], (void)&return_value[i] ) ;
printf ( "input = %ld output=%ld \n",i, return_value[i] );
}
return (0) ;
pthread_exit
Terminate the calling thread
void pthread_exit (void *retval);
pthread_join
int pthread_join (pthread_t th,void **returnval);
Sharing data
Threads can collaborate on the same data
(shared memory)
Suppose that two (or more) concurrently running threads
both try to increment an integer variable I:
thread 1: I=I+2
thread 2: I=I+3
Race condition
It is problematic!
The result of these updates depends on the order of
execution:
Spawning threads
We already mentioned that threads share the same
memory space.
This could cause some troubles.
In the following are some examples:
(details are not SO important)
Spawning threads
In the following example
1. some threads are created
2. the update a shared variable
3. The Threads join again
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 26
forking
function adder()
joining
Spawning threads
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Listing 3: spawnThreads.c
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 27
Spawning threads
1
2
3
4
5
Now all threads read out the value of sum, wait a while
(presumably calculating something) and then update,
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 29
Mutually exclusive
We can fix this behaviour by having a lock on the code region
that should be mutually exclusive
7 pthread_mutex_t lock;
8
9 void adder() {
10
int t , r ;
11
pthread_mutex_lock(&lock);
12
t = sum;
13
sleep(1);
14
sum = t +1;
15
pthread_mutex_unlock(&lock);
16
return ;
22
23
pthread_t th [NTHREADS];
pthread_mutex_init(&lock,NULL);
Listing 5: spawnThreadsMutex.c
1
2
3
4
5
Mutex variables
Mutex
Mutex is an abbreviation for mutual exclusion.
They can be used to prevent raceconditions.
Mutex variables are one of the primary means of
implementing thread synchronization and for protecting
shared data when multiple writes occur.
A mutex variable acts like a lockprotecting access to a
shared data resource.
The basic concept is that only one thread can lock
(or own) a mutex variable at any given time.
Thus, even if several threads try to lock a mutex only one
thread will be successful.
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 31
Mutex sequence
A typical sequence in the use of a mutex is as follows:
Create and initialize a mutex variable
Several threads attempt to lock the mutex
Only one succeeds and that thread owns the mutex
The owner thread performs some set of actions
The owner unlocks the mutex
Another thread acquires the mutex and repeats the
process
Finally the mutex is destroyed
Locks
When your code accesses some memory, you lock it up:
mutex: the lock.
critical section: the code locked with a
mutex.
Now if a thread wants to run this code, he needs the key. So
only one thread can run the code at a time:
Critical section
Code in a critical section
Mutex creation
Declaration
Mutex variables must be declared with type
pthread_mutex_t
They must be initialized before they can be use
Initialization
There are two ways to initialize a mutex variable:
Statically, when it is declared. For example:
pthread_mutex_t mymutex =
PTHREAD_MUTEX_INITIALIZER;
Dynamically, with the pthread_mutex_init() routine.
Mutex locking
pthread_mutex_lock()
This routine is used by a thread to acquire a lock on the
specified mutex variable.
If the mutex is already locked by another thread, this call
will block the calling thread until the mutex is unlocked.
pthread_mutex_trylock()
This routine will attempt to lock a mutex.
However, if the mutex is already locked, the routine will
return immediately with a busy error code.
Useful in preventing deadlock conditions,
as in a priority-inversion situation.
pthread_mutex_unlock()
This routine unlock a mutex if called by the owning thread.
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 36
//
// This program computes the scalar product of two vectors using pthreads.
#include
#include
#include
#include
<pthread.h>
<sys/time.h>
< stdlib .h>
<stdio.h>
Listing 6: scalarProd.c
20. April 2015 Thorsten Grahs Parallel Computing I SS 2015 Seite 37
printf ( "B
= ");
for ( i =0; i < vec_length; i ++)
printf ( " %.2f ",vecB[i]) ;
printf ( " \n") ;
printf ( "A.B =
%.6f\n ",global_sum);
ret_count=pthread_attr_destroy(&pta);
time_estimate(t1,t2) ;
return (0) ;
Resume
Why treads are important for parallel computing?
Threads are independent stream of instructions which
could easily create concurrency.
There are light-weighted i.e. easy to create with less
overhead
There offer a natural programming model for shared
address spaces.
OpenMP is based on cooperating threads running
simultaneously on multiple processors ore cores.
OpenMP will be covered in the next lectures
Further readings
POSIX Threads Programming
Blaise Barney, Lawrence Livermore National Laboratory
https://computing.llnl.gov/tutorials/pthreads
Advanced Linux Programming
Coude sourcery
Chapter 4: Threads
http://www.advancedlinuxprogramming.com
Parallel Programming
T. Rauber & G. Rnger
Chapter 6: Thread programming
Springer 2007.