POSIX Threads Programming Exercise

  1. Login to the SP machine

    Workshops differ in how this is done. The instructor will go over this beforehand.

  2. 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

  3. 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.
    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.

  4. 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

  5. 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.

  6. 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.

  7. 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:

    1. Immediately before the line containing the pthread_mutex_lock call, add a line with a sleep(3); call.

    2. 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.

    3. 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);

    4. 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.

    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:

    1. 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.

    2. In the main routine, comment-out the last statement line which contains the pthread_exit call.

    3. Compile and run your modified hello.c program. What happens? Why?

    4. Now, put the pthread_exit call back into the main program, but remove it from the PrintHello subroutine.

    5. 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.

    1. 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.

    2. Compile and run the program. What happens? Notice the order in which thread output is displayed. How is this explained?

    3. 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?

    4. 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?

  8. Try the mpithreads series of codes

    1. 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.

    2. As time permits, review each of the codes. (The order of the listing above shows the "progression").

    3. 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.

    4. 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

    5. 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.


This concludes the POSIX Threads exercise.