- Login to the SP machine
Workshops differ in how this is done. The instructor will go over this
beforehand.
- Copy the example files
In your home directory, create a subdirectory for the example codes
and cd to it. Then copy the Pthreads example codes.
mkdir ~/pthreads
cd ~/pthreads
cp /usr/local/spclass/blaise/pthreads/samples/* ~/pthreads
- List the contents of your pthreads subdirectory
You should notice quite a few files, comprising both the exercise codes and
sample output files. The table below describes these files in alphabetical
order.
File Name
| Description
|
arrayloops.c
arrayloops.f
| Data decomposition by loop distribution. Fortran example
requires IBM Pthreads library module - see program comments.
|
condvar1.c
condvar1.out
| Condition variable example source file and sample output
file.
|
condvar2.c
condvar2_sol.c
| Similar to condvar1.c except this example has a BUG. The condvar_sol.c
file provides the solution to the bug.
|
dotprod_mutex.c
dotprod_serial.c
| Mutex variable example using a dot product program. Both
a serial and pthreads version of the code are available.
|
hello.c
hello.out
| "Hello World" pthreads source file and sample output file
|
hello512.c
| "Hello World" pthreads program demonstrating thread resource limits
|
hello_arg1.c
hello_arg1.out
| Correct passing of pthread_create() arguments. Source file
and sample output file.
|
hello_arg2.c
hello_arg2.out
| Another correct method of passing pthread_create()
arguments, this time using a structure to pass multiple arguments. Source
file and sample output file.
|
hello_arg3.c
hello_arg3.out
| Incorrect passing of pthread_create() arguments. Source
file and sample output file.
|
hellodump.c
hellodumpfix.c
| "Hello World" pthreads program that crashes because of thread
resource limits. Also included is a "fix" for the problem.
|
join1.c
join1.out
| Demonstrates how to explicitly create pthreads in a joinable state
for portability purposes. Source file and sample output file.
|
minim1.c
| Minimum pthreads program - similar to "Hello World"
|
minim2.c
| Another minimum pthreads program - includes detach/join
|
mpithreads_both.c
mpithreads.makefile
mpithreads_mpi.c
mpithreads_serial.c
mpithreads_threads.c
| A "series" of programs which demonstrate the progression
for a serial dot product code to a hybrid MPI/Pthreads implementation.
Files include the serial version, Pthreads version, MPI version,
hybrid version and a makefile.
|
- Review and compile hello.c
Begin with the simplest exercise code. After reviewing and understanding
what hello.c does, use the thread-safe, IBM C compiler to compile
the source code:
xlc_r -o hello hello.c
- Run the hello executable
Run the executable and notice its output.
hello
Does it resemble the sample output in hello.out? Try running it
several times and notice if the output changes. Then, modify the source
code to increase the number of threads which are created. Compile and
run your modified version.
- Review, compile and run the other Pthreads example codes
With the exception of the mpithreads set of codes, select any/all
of the other Pthreads codes to review, compile and run as done with
the hello.c example code above.
- Some things to try...
Part of the learning process is to see what happens when things go wrong.
The following exercises will ask you to modify the example codes to
introduce / fix errors.
Condition Variable Synchronization Errors
One logical error which can lead to a program "hanging" is for a thread
to signal on a condition variable before the receiving thread is ready to
catch the signal. Using the condvar1.c program, edit the
watch_count routine as follows:
- Immediately before the line containing the pthread_mutex_lock
call, add a line with a sleep(3); call.
- Compile and run the program. What happens? It should run to
completion because the while condition prevents execution
of the pthread_cond_wait routine if the signal has already
been sent.
- Now, edit the watch_count routine to remove the while
loop (but do leave the sleep(3); statement as is). Your
code block should look like this:
sleep(3);
pthread_mutex_lock(&count_mutex);
pthread_cond_wait(&count_threshold_cv, &count_mutex);
printf("watch_count(): thread %d Condition signal received.\n", *my_id);
pthread_mutex_unlock(&count_mutex);
pthread_exit(NULL);
- Compile and run the program. What happens this time? Why? When you're
convinced that the program is "hung", hit CTRL-C to terminate it.
Condition Variable Signal Starvation
Another logical error is signal starvation. Compile and run the
condvar2.c example code. It should hang. Figure out why
and fix the problem. The solution file is condvar2_sol.c.
Exit / Termination Errors
There are several ways for threads to terminate. One way to safely
terminate, particularly for a thread which has created other threads, is
to call the pthread_exit() routine. In this exercise, modify
your hello.c program as follows:
- In the PrintHello routine, add a line before the printf
call which looks like: sleep(1);. This should be the first line
of the subroutine.
- In the main routine, comment-out the last statement
line which contains the pthread_exit call.
- Compile and run your modified hello.c program. What happens?
Why?
- Now, put the pthread_exit call back into the main program,
but remove it from the PrintHello subroutine.
- Compile and run your modified hello.c program. What happens?
Why?
Resource Related Errors
Pthread implementations will differ in the limits enforced for thread
resource usage.
- Review the example code hello512.c. Note that it
will create 512 threads. A sleep(); statement has been
introduced to insure that all threads will be in existence at the same
time. Also, each thread performs actual work to demonstrate how the
AIX scheduler behavior determines the order of thread completion.
- Compile and run the program. What happens? Notice the order in which
thread output is displayed. How is this explained?
- Modify the program so that it attempts to create 5000 threads. Then
compile and run it. What happens this time? What does the error code
mean? (hint: consult the
pthread_create() man page in conjunction with the
/usr/include/errno.h file) Does it make sense?
- Now try the program hellodump.c. Compile and run it.
What happens? The challenge here is to determine why the program
fails and to fix it. (Hint: it has to do with a resource limit).
The hellodumpfix.c example shows one way to fix the
problem - how does it match your ideas?
- Try the mpithreads series of codes
-
Your pthreads directory should contain the following 5 codes:
mpithreads_serial.c
mpithreads_threads.c
mpithreads_mpi.c
mpithreads_both.c
mpithreads.makefile
These codes implement a dot product calculation and are designed to show
the progression of developing a hybrid MPI / Pthreads program from a
a serial code.
- As time permits, review each of the codes. (The order of the
listing above shows the "progression").
- Use the provided makefile to compile all of the codes at once:
make -f mpithreads.makefile
Be sure to examine the makefile so that you are familiar with the
actual compiler commands used.
- Run each of the codes. Note: in order to run the two codes which
use MPI (mpithreads_mpi and mpithreads_both),
you must first have the necessary POE environment
variables set, as shown below.
Environment Variable
| Setting
| Description
|
MP_PROCS
| 4
| The number of MPI tasks will be 4
|
MP_NODES
| 4
| Only one MPI task per node (threads will utilize all cpus)
|
MP_RMPOOL
| poolid
| Set poolid to the workshop pool number.
Ask the instructor, or click
to determine the workshop node pool.
|
MP_EUILIB
| us
| Use User Space protocol communications (fastest)
|
MP_RESD
| yes
| Allow the Resource Manager to select the nodes automatically
|
- Suggestion: simply running this series of codes is rather unremarkable.
Using the available lab time to understand what is actually happening
is the intent. The instructor is available for your questions.