1. Goals for these weeks:
-
Learn how to write a pthreads program
-
Learn some Learn some Unix commands for finding out information about cpus and threads running in the system
-
Reminder about ParaVis library and a pthreads ParaVis example
-
Practice with some debugging techniques for pthread programs
2. Starting Point Code
Start by creating a week12 directory in
your cs31/weeklylab
subdirectory and copying over some files:
cd ~/cs31/weeklylab
mkdir week12
cd week12
pwd
/home/you/cs31/weeklylab/week12
cp ~newhall/public/cs31/week12/* .
ls
3. Example pthread Program with a race condition
Let’s look at the hello.c
program together. It show an example of
a simple pthreads program that:
-
spawns some worker threads by calling
pthread_create
-
passes parameter values (thread logical identifier values) to each thread’s main function via its
void *args
parameter.This shows an example of how the thread main loop function can get is argument value(s) from it parameter
-
calls to
pthread_join
to wait for all spawned threads to exit.
Let’s try running it a few times with different numbers of threads.
You can view some notes about pthread programming and this example here too:
evince ~newhall/public/cs31/pthreads.pdf
This program is an example of a multi-threaded program with a race condition. Let’s try to fix it using some pthread synchronization primitives. But first, lets look at the following program that has some examples of using pthread synchronization primatives…
4. Example pthread program that uses synchronization primitives
The synch.c
contains some examples using pthreads
mutex and barrier synchronization. It also shows an example of defining
a struct type that can be used to pass several values to a threads main
function via its single void *args
parameter. Try running this to
see understand what it is doing. Then go back and fix the hello.c
program by adding in some synchronization to remove the race condition.
5. top, htop, and threads
top and htop are Unix utilities that list information about processes and threads and how they are using resources like memory and CPU. If you run top with no command line options, then it displays per-process statistics. If you run top with -H, top will display statistics for individual threads (if you run the synch program for a large number of threads, you can see them show up in top):
top -H
Let’s try out the example of configuring top from this page: using top and htop to change what top displays. Then we can try running a multi-threaded process and see what top shows us.
Let’s run the synch
program with a bunch of threads, and then top -H in
another window to see what we can see.
We can also try running htop
.
We can also see the number of CPU cores on a particular machine, and a lot
of information about each one, by looking at a file in the /proc
file system:
cat /proc/cpuinfo | more
(| more
pipes cat
output through the more
reader that allows you to
scroll through a page at a time using the space bar, enter q
to quit):
6. ParaVis pthread example
We are not going to talk about this in lab, but with the in-lab code is an example visualization that uses the ParaVis animation library. This is very similar to the one we looked at in Weekly Lab 9, but it is an example of a parallel pthread animation. The comment at the top describes the sequence of ParaVis library calls that an application needs to make to visualize their computation.
7. debugging pthread programs
Debugging threaded programs can be tricky because there are multiple
streams of execution. In general, try to debug with as few threads
as possible, and if you use printfs, print out a thread id and call
fflush after. You can also put printf’s in conditional statements
to only have one of the threads print out information (or only
some of the threads, or only some of the information, …).
For example, if each thread is passed a logical thread id value
on start-up, and stores its value in a local variable named my_tid
then you could have logical thread 1 be the debug output printing thread
to do something like:
if(my_tid == 1) {
printf("Tid:%d: value of count is now %d my i is %d\n", my_tid,count,i);
fflush(stdout);
}
7.1. gdb and pthreads
gdb has support for debugging multi-threaded processes. If you want to try using gdb to debug your pthread code, here is some general information about it and an example you can try out: Debugging pthreads programs with gdb. It contains an example run of debugging the racecond program you copied over with this week’s in-class code.
More detailed information about gdb and pthreads can be found:
-
and another reference on gdb and pthreads
8. Handy References
-
-
Chapter 2: C programming (strings, 2D arrays), and (2.9.3 void * type)
-
Chapter 3: C debugging tools (valgrind, gdb for C, 3.6 gdb and pthreads).
-
Chapter 10: pthread programming
-
-
man pages for more information about pthread and other library functions.
-
My C Programming Resources and Links including the C Style Guide, I/O in C, cmdline args, arrays, libraries, Makefiles.