# CS 5220 ## Shared memory ### Pthreads ## 22 Sep 2015
### Shared memory programming model Program consists of *threads* of control. - Can be created dynamically - Each has private variables (e.g. local) - Each has shared variables (e.g. heap) - Communication through shared variables - Coordinate by synchronizing on variables - Examples: OpenMP, *pthreads*, Cilk, Java threads
### Concrete code: pthreads - pthreads = POSIX threads - Standardized across UNIX family - Fairly low-level - Heavy weight?

Thread birth and death


Thread is created by forking.
When done, join original thread.

### Thread birth and death void thread_fun(void* arg); pthread_t thread_id; pthread_create(&thread_id, &thread_attr, thread_fun, &fun_arg); // ... pthread_join(&thread_id, NULL);

Mutex


Allow only one process at a time in critical section (red).
Synchronize via locks, aka mutexes (mutual exclusion vars).

### Mutex pthread_mutex_t l; pthread_mutex_init(&l, NULL); // ... pthread_mutex_lock(&l); /* Critical section here */ pthread_mutex_unlock(&l); // ... pthread_mutex_destroy(&l);

Condition variables


Thread waits until condition holds (e.g. work available).

Condition variables


pthread_mutex_t l;
pthread_cond_t cv;
pthread_mutex_init(&l)
pthread_cond_init(&cv, NULL);

/* Thread 0 */
mutex_lock(&l);
add_work();
cond_signal(&cv);
mutex_unlock(&l);

/* Thread 1 */
mutex_lock(&l);
if (!work_ready)
    cond_wait(&cv, &l);
get_work();
mutex_unlock();

pthread_cond_destroy(&cv);
pthread_mutex_destroy(&l);

Barriers


Computation phases separated by barriers.
Everyone reaches the barrier, then proceeds.

### Barriers pthread_barrier_t b; pthread_barrier_init(&b, NULL, nthreads); // ... pthread_barrier_wait(&b); // ...
### Example: Work queues - Job composed of different tasks - Work gang of threads to execute tasks - Maybe tasks can be added over time? - Want dynamic load balance
### Example: Work queues Basic data: - Gang of threads - Work queue data structure - Mutex protecting data structure - Condition to signal work available - Flag to indicate all done?
### Example: Work queues task_t get_task() { task_t result; pthread_mutex_lock(&task_l); if (done_flag) { pthread_mutex_unlock(&task_l); pthread_exit(NULL); } if (num_tasks == 0) pthread_cond_wait(&task_ready, &task_l); // ... Remove task from data struct ... pthread_mutex_unlock(&task_l); return result; }
### Example: Work queues void add_task(task_t task) { pthread_mutex_lock(&task_l); ... Add task to data struct ... if (num_tasks++ == 0) pthread_cond_signal(&task_ready); pthread_mutex_unlock(&task_l); }
### The problem with pthreads Portable standard, but... - Low-level library standard - Verbose - Makes it easy to goof on synchronization - Compiler doesn’t help out much OpenMP is a common alternative.