OpenMP Basics for Programmers
OpenMP Basics for Programmers
1 2
• OpenMP doesn’t check for data dependencies, data conflicts, deadlocks, or race
conditions. You are responsible for avoiding those yourself
• OpenMP doesn’t check for non-conforming code sequences (we'll talk about what this
means)
• OpenMP doesn’t guarantee the order in which threads execute, just that they do execute
• OpenMP does not prevent you from writing code that triggers cache performance
problems (such as in false-sharing), in fact, it makes it really easy
3 4
Stack Stack
Using OpenMP in Microsoft Visual Studio
Don’t take this completely
1. Go to the Project menu → Project Properties
literally. The exact Common
arrangement depends on the
Program operating system and the Program
Executable compiler. For example, Executable
sometimes the stack and heap 2. Change the setting Configuration Properties → C/C++ → Language →
are arranged so that they grow OpenMP Support to "Yes (/openmp)"
towards each other.
Globals Common
Globals If you are using Visual Studio and get a compile message that looks like this:
1>c1xx: error C2338: two-phase name lookup is not supported for C++/CLI, C++/CX, or OpenMP; use /Zc:twoPhase-
then do this:
5 6
1
7 Numbers of OpenMP threads 8
Seeing if OpenMP is Supported on Your System
#ifdef _OPENMP
fprintf( stderr, "OpenMP release %d is supported here\n", _OPENMP ); How to specify how many OpenMP threads you want to have available:
#else omp_set_num_threads( num );
fprintf( stderr, "OpenMP is not supported here – sorry!\n" );
return 1;
Asking how many cores this program has access to:
#endif Actually returns the number of hyperthreads,
num = omp_get_num_procs( );
not the number of physical cores
Printing _OPENMP gives you a year and month of the OpenMP release that you are using
Setting the number of available threads to the exact number of cores available:
To get the OpenMP version number from the year and month, check here:
OpenMP 5.0 – November 2018 omp_set_num_threads( omp_get_num_procs( ) );
OpenMP 4.5 – November 2015
Asking how many OpenMP threads this program is using right now:
OpenMP 4.0 – July 2013
num = omp_get_num_threads( );
OpenMP 3.1 – July 2011
OpenMP 2.0 – March 2002 Asking which thread number this one is:
OpenMP 1.0 – October 1998 me = omp_get_thread_num( );
• By default, flip uses g++ 11.4, which uses OpenMP version 4.5
• Visual Studio 2022 uses OpenMP 2.0
Computer Graphics Computer Graphics
mjb – April 9, 2024 mjb – April 9, 2024
7 8
Creating an OpenMP Team of Threads 9 The OpenMP Thread Team Prints a Friendly Message 10
9 10
11 12
2
OpenMP for-Loop Rules 13 OpenMP For-Loop Rules 14
index++
++index
• The index must be an int or a pointer index < end index--
• The start and terminate conditions must have compatible types index <= end ; --index
for( index = start ; )
index > end index += incr
• Neither the start nor the terminate conditions can be changed during the index = index + incr
execution of the loop
index >= end
index = incr + index
• The index can only be modified by the changed expression (i.e., not index -= decr
modified inside the loop itself) index = index - decr
• You cannot use a break or a goto to get out of the loop
• There can be no inter-loop data dependencies such as:
a[ i ] = a[ i-1 ] + 1.;
a[101] = a[100] + 1.; // what if this is the last line of thread #0’s work?
a[102] = a[101] + 1.; // what if this is the first line of thread #1’s work?
13 14
What to do about Variables Declared Before the for-loop Starts? 15 For-loop “Fission” 16
float x = 0.; Because of the loop dependency, this whole thing is not parallelizable:
#pragma omp parallel for …
x[ 0 ] = 0.;
for( int i = 0; i < N; i++ )
{
y[ 0 ] *= 2.;
i and y are automatically private because they are for( int i = 1; i < N; i++ )
x = (float) i;
defined within the loop. {
float y = x*x;
<< more code… > x[ i ] = x[ i-1 ] + 1.;
} Good practice demands that x be explicitly y[ i ] *= 2.;
declared to be shared or private!
}
private(x)
Means that each thread will get its own version of the variable
But it can be broken into one loop that is not parallelizable, plus one that is:
shared(x) x[ 0 ] = 0.;
Means that all threads will share a common version of the variable for( int i = 1; i < N; i++ )
{
default(none) x[ i ] = x[ i-1 ] + 1.;
I recommend that you include this in your OpenMP for-loop directive. This will }
force you to explicitly flag all of your externally-declared variables as shared or
private. Don’t make a mistake by leaving it up to the default! #pragma omp parallel for shared(y)
for( int i = 0; i < N; i++ )
{
Example:
y[ i ] *= 2.;
#pragma omp parallel for default(none), private(x)
}
Computer Graphics Computer Graphics
mjb – April 9, 2024 mjb – April 9, 2024
15 16
17 18
3
OpenMP Allocation of Work to Threads 19 OpenMP Allocation of Work to Threads 20
19 20
Computer Graphics Conclusion: Don’t do it this way! Don’t do it this way! We’ll talk about how to do it correctly in the Trapezoid Integration noteset.
Computer Graphics
mjb – April 9, 2024 mjb – April 9, 2024
21 22
Barriers
#pragma omp barrier
Forces each thread to wait here until all threads arrive
(Note: there is an implied barrier after parallel for loops and OpenMP sections,
unless the nowait clause is used)
23 24
4
Synchronization Example 25 Single-thread-execution Synchronization 26
omp_lock_t Sync;
...
omp_init_lock( &Sync ); #pragma omp single
Restricts execution to a single thread ever. This is used when an operation only
... makes sense for one thread to do. Reading data from a file is a good example.
25 26
27 28
29
A Potential OpenMP/Visual Studio Compiler Problem
If you print to standard error (stderr) from inside a for-loop, like I do, then
you think that you need to include stderr in the shared list because, well,
the loops share it:
If you are using Visual Studio, then do not include stderr in the list.
If you do, you will get this error:
This is because:
• In g++/gcc, stderr is a variable
• In Visual Studio, stderr is a defined macro
Computer Graphics
mjb – April 9, 2024
29