Friday, December 17, 2010

What is OpenMP? What does OpenMP code look like?

OpenMP is an easy cross platform way of making code multi-threaded. You just sprinkle in a magic pragma before a for loop, and presto, the cycles of the loop get spread across multiple cores.

Here’s a simple example (written in Visual Studio 2008).

#include "stdafx.h"
#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

int _tmain (int argc, char *argv[])
{
#pragma omp parallel for
    for (int i = 0; i < 20; i++)
    {
        int threadId = omp_get_thread_num();
        printf("Hello World from thread %d\n", threadId);
        if ( threadId == 0 )
        {
            printf("%d threads\n", omp_get_num_threads());
            printf("In Parallel Region = %d\n", omp_in_parallel());
        }
    }

    _getch();
    return EXIT_SUCCESS;
}

Here’s the output on a machine with 12 cores:

Hello World from thread 0
There are 12 threads
In Parallel Region = 1
Hello World from thread 0
There are 12 threads
In Parallel Region = 1
Hello World from thread 11
Hello World from thread 3
Hello World from thread 3
Hello World from thread 9
Hello World from thread 1
Hello World from thread 1
Hello World from thread 10
Hello World from thread 7
Hello World from thread 7
Hello World from thread 8
Hello World from thread 6
Hello World from thread 6
Hello World from thread 4
Hello World from thread 4
Hello World from thread 2
Hello World from thread 2
Hello World from thread 5
Hello World from thread 5

There’s some interesting things to see about this output:

  • There are 12 threads – 0..11.
  • Some threads run one cycle (e.g. #10) and others run multiple cycles (e.g. #5).
  • You can see where thread 0 runs the conditional code.

Getting More Complicated

A simple loop like the one above is fine as it is. Once you start trying to do real work, you quickly bump into the problem that you need to think about whether variables are ‘shared between all threads’ or ‘private to each thread’.

I first recommend adding the ‘clause’ of ‘default(none)’. This will force the compiler to make you explicitly define whether variables are shared or private. Shared and private variables are then specified in a comma separated list. Here’s an example of what the pragma line now looks like:

#pragma omp parallel for default(none) private(myVar, foo) shared(someOtherVar, andAnother)

I’m no expert on OpenMP, and there’s a lot more to it that’s not covered here. The wikipedia page is pretty good for more info.

Some notes:

  • The omp.h header comes with Visual Studio. There’s no lib file needed.
  • You need to enable OpenMP in the project settings (C/C++ –> Language –> OpenMP Support –> Yes).

No comments: