29
OpenMP Tutorial The OpenMP API for Multithreaded Programming 1 1 OpenMP * in Action Tim Mattson Intel Corporation Acknowledgements: Acknowledgements: Acknowledgements: Acknowledgements: Rudi Eigenmann of Purdue, Sanjiv Shah of Intel and others too numerous to name have contributed content for this tutorial. Barbara Chapman University of Houston * The name “OpenMP” is the property of the OpenMP Architecture Review Board. 2 Agenda Parallel computing, threads, and OpenMP The core elements of OpenMP Thread creation Workshare constructs Managing the data environment Synchronization The runtime library and environment variables Recapitulation

OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

  • Upload
    others

  • View
    20

  • Download
    0

Embed Size (px)

Citation preview

Page 1: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 1

1

OpenMP* in Action

Tim MattsonIntel Corporation

Acknowledgements: Acknowledgements: Acknowledgements: Acknowledgements: Rudi Eigenmann of Purdue, Sanjiv Shah of Intel and others too numerous to name have contributed content for this tutorial.

Barbara ChapmanUniversity of Houston

* The name “OpenMP” is the property of the OpenMP Architecture Review Board.

2

Agenda

� Parallel computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

Page 2: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 2

3

OpenMP* Overview:

omp_set_lock(lck)

#pragma omp parallel for private(A, B)

#pragma omp critical

C$OMP parallel do shared(a, b, c)

C$OMP PARALLEL REDUCTION (+: A, B)

call OMP_INIT_LOCK (ilok)

call omp_test_lock(jlok)

setenv OMP_SCHEDULE “dynamic”

CALL OMP_SET_NUM_THREADS(10)

C$OMP DO lastprivate(XX)

C$OMP ORDERED

C$OMP SINGLE PRIVATE(X)

C$OMP SECTIONS

C$OMP MASTERC$OMP ATOMIC

C$OMP FLUSH

C$OMP PARALLEL DO ORDERED PRIVATE (A, B, C)

C$OMP THREADPRIVATE(/ABC/)

C$OMP PARALLEL COPYIN(/blk/)

Nthrds = OMP_GET_NUM_PROCS()

!$OMP BARRIER

OpenMP: An API for Writing Multithreaded Applications

�A set of compiler directives and library routines for parallel application programmers

�Greatly simplifies writing multi-threaded (MT) programs in Fortran, C and C++

�Standardizes last 20 years of SMP practice

* The name “OpenMP” is the property of the OpenMP Architecture Review Board.

4

What are Threads?

� Thread: an independent flow of control�Runtime entity created to execute sequence of instructions

� Threads require:

�A program counter

�A register state

�An area in memory, including a call stack

�A thread id

� A process is executed by one or more threads that share:�Address space

�Attributes such as UserID, open files, working directory, etc.

Page 3: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 3

5

A Shared Memory Architecture

proc1 proc2 proc3 procN

Shared memory

cache1 cache2 cache3 cacheN

6

How Can We Exploit Threads?

�A thread programming model must provide (at least) the means to:

�Create and destroy threads

�Distribute the computation among threads

�Coordinate actions of threads on shared data

�(usually) specify which data is shared and which is private to a thread

Page 4: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 4

7

How Does OpenMP Enable Us to Exploit Threads?

� OpenMP provides thread programming model at a “high level”. �The user does not need to specify all the details

– Especially with respect to the assignment of work to threads

– Creation of threads

� User makes strategic decisions

� Compiler figures out details

� Alternatives:�MPI

�POSIX thread library is lower level

�Automatic parallelization is even higher level (user does nothing)

– But usually successful on simple codes only

8

OpenMP Overview:How do threads interact?

� OpenMP is a shared memory model.– Threads communicate by sharing variables.

� Unintended sharing of data causes race conditions:

– race condition: when the program’s outcome changes as the threads are scheduled differently.

� To control race conditions:– Use synchronization to protect data conflicts.

� Synchronization is expensive so:– Change how data is accessed to minimize the need

for synchronization.

Page 5: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 5

9

Agenda

� Parallel Computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

10

OpenMP:Some syntax details to get us started

� Most of the constructs in OpenMP are compiler directives.�For C and C++, the directives are pragmas with the form:

#pragma omp construct [clause [clause]�]

�For Fortran, the directives are comments and take one of the forms:

– Fixed form*$OMP construct [clause [clause]…]

C$OMP construct [clause [clause]…]

– Free form (but works for fixed form too)!$OMP construct [clause [clause]…]

� Include file and the OpenMP lib module#include <omp.h>

use omp_lib

Page 6: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 6

11

#pragma omp parallel

{

int id = omp_get_thread_num();

more: res[id] = do_big_job(id);

if(!conv(res[id]) goto more;

}

printf(“ All done \n”);

#pragma omp parallel

{

int id = omp_get_thread_num();

more: res[id] = do_big_job(id);

if(!conv(res[id]) goto more;

}

printf(“ All done \n”);

� Most OpenMP* constructs apply to structured blocks.

– Structured block: a block with one point of entry at the top and one point of exit at the bottom.

– The only “branches” allowed are STOP statements in Fortran and exit() in C/C++.

if(go_now()) goto more;

#pragma omp parallel

{

int id = omp_get_thread_num();

more: res[id] = do_big_job(id);

if(conv(res[id]) goto done;go to more;

}

done: if(!really_done()) goto more;

if(go_now()) goto more;

#pragma omp parallel

{

int id = omp_get_thread_num();

more: res[id] = do_big_job(id);

if(conv(res[id]) goto done;go to more;

}

done: if(!really_done()) goto more;

A structured block Not A structured block

OpenMP:Structured blocks (C/C++)

12

OpenMP:Structured Block Boundaries

� In C/C++: a block is a single statement or a group of

statements between brackets {}

� In Fortran: a block is a single statement or a group of

statements between directive/end-directive pairs.

C$OMP PARALLEL

10 wrk(id) = garbage(id)

res(id) = wrk(id)**2

if(.not.conv(res(id)) goto 10

C$OMP END PARALLEL

C$OMP PARALLEL

10 wrk(id) = garbage(id)

res(id) = wrk(id)**2

if(.not.conv(res(id)) goto 10

C$OMP END PARALLEL

C$OMP PARALLEL DO

do I=1,Nres(I)=bigComp(I)

end do

C$OMP END PARALLEL DO

C$OMP PARALLEL DO

do I=1,Nres(I)=bigComp(I)

end do

C$OMP END PARALLEL DO

#pragma omp parallel

{

id = omp_thread_num();

res(id) = lots_of_work(id);

}

#pragma omp parallel

{

id = omp_thread_num();

res(id) = lots_of_work(id);

}

#pragma omp for

for(I=0;I<N;I++){

res[I] = big_calc(I);

A[I] = B[I] + res[I];

}

#pragma omp for

for(I=0;I<N;I++){

res[I] = big_calc(I);

A[I] = B[I] + res[I];

}

Page 7: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 7

13

Agenda

� Parallel computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

� The OpenMP compiler

� OpenMP usage: common design patterns

� Case studies and examples

� Background information and extra details

14

The OpenMP* API

Parallel Regions

� You create threads in OpenMP* with the “omp parallel” pragma.

� For example, To create a 4 thread Parallel region:

double A[1000];omp_set_num_threads(4);#pragma omp parallel{

int ID = omp_get_thread_num();pooh(ID,A);

}

�� Each thread calls Each thread calls pooh(ID,A) for for IDIDIDID = = 0000 to to 3333

Each thread executes a copy of the

code within

the structured

block

Each thread executes a copy of the

code within

the structured

block

Runtime function to request a certain number of threads

Runtime function to request a certain number of threads

Runtime function returning a thread IDRuntime function returning a thread ID

* The name “OpenMP” is the property of the OpenMP Architecture Review Board

Page 8: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 8

15

The OpenMP* API

Parallel Regions

� Each thread executes the same code redundantly.

double A[1000];omp_set_num_threads(4);

#pragma omp parallel{

int ID = omp_get_thread_num();pooh(ID, A);

}

printf(“all done\n”);omp_set_num_threads(4)

pooh(1,A) pooh(2,A) pooh(3,A)

printf(“all done\n”);

pooh(0,A)

double A[1000];

A single copy of A is shared between all threads.

A single copy of A is shared between all threads.

Threads wait here for all threads to finish before proceeding (i.e. a barrier)Threads wait here for all threads to finish before proceeding (i.e. a barrier)

* The name “OpenMP” is the property of the OpenMP Architecture Review Board

16

Exercise:A multi-threaded “Hello world” program

� Write a multithreaded program where each thread prints “hello world”.

void main(){

int ID = 0;

printf(“ hello(%d) ”, ID);printf(“ world(%d) \n”, ID);

}

void main(){

int ID = 0;

printf(“ hello(%d) ”, ID);printf(“ world(%d) \n”, ID);

}

Page 9: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 9

17

Exercise:A multi-threaded “Hello world” program

� Write a multithreaded program where each thread prints “hello world”.

#include “omp.h”void main(){

#pragma omp parallel{

int ID = omp_get_thread_num();printf(“ hello(%d) ”, ID);printf(“ world(%d) \n”, ID);

}}

#include “omp.h”void main(){

#pragma omp parallel{

int ID = omp_get_thread_num();printf(“ hello(%d) ”, ID);printf(“ world(%d) \n”, ID);

}}

Sample Output:

hello(1) hello(0) world(1)

world(0)

hello (3) hello(2) world(3)

world(2)

Sample Output:

hello(1) hello(0) world(1)

world(0)

hello (3) hello(2) world(3)

world(2)

OpenMP include file

Parallel region with default Parallel region with default Parallel region with default Parallel region with default number of threadsnumber of threadsnumber of threadsnumber of threads

Runtime library function to Runtime library function to Runtime library function to Runtime library function to return a thread ID.return a thread ID.return a thread ID.return a thread ID.End of the Parallel regionEnd of the Parallel regionEnd of the Parallel regionEnd of the Parallel region

18

Agenda

� Parallel computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

Page 10: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 10

19

OpenMP: Work-Sharing Constructs

� The “for” Work-Sharing construct splits up loop iterations among the threads in a team

#pragma omp parallel#pragma omp for

for (I=0;I<N;I++){NEAT_STUFF(I);

}

By default, there is a barrier at the end of the “omp for”. Use the “nowait” clause to turn off the barrier.

#pragma omp for nowait

“nowait” is useful between two consecutive, independent omp for loops.

20

Work Sharing ConstructsA motivating example

for(i=0;I<N;i++) { a[i] = a[i] + b[i];}for(i=0;I<N;i++) { a[i] = a[i] + b[i];}

#pragma omp parallel{

int id, i, Nthrds, istart, iend;id = omp_get_thread_num();Nthrds = omp_get_num_threads();istart = id * N / Nthrds;iend = (id+1) * N / Nthrds;for(i=istart;I<iend;i++) { a[i] = a[i] + b[i];}

}

#pragma omp parallel{

int id, i, Nthrds, istart, iend;id = omp_get_thread_num();Nthrds = omp_get_num_threads();istart = id * N / Nthrds;iend = (id+1) * N / Nthrds;for(i=istart;I<iend;i++) { a[i] = a[i] + b[i];}

}

#pragma omp parallel #pragma omp for schedule(static)

for(i=0;I<N;i++) { a[i] = a[i] + b[i];}

#pragma omp parallel #pragma omp for schedule(static)

for(i=0;I<N;i++) { a[i] = a[i] + b[i];}

Sequential code

OpenMP parallel region

OpenMP parallel region and a work-sharing for-construct

Page 11: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 11

21

OpenMP For/Do construct:The schedule clause

� The schedule clause affects how loop iterations are mapped onto threads

�schedule(static [,chunk])

– Deal-out blocks of iterations of size “chunk” to each thread.

�schedule(dynamic[,chunk])

– Each thread grabs “chunk” iterations off a queue until all iterations have been handled.

�schedule(guided[,chunk])

– Threads dynamically grab blocks of iterations. The size of the block starts large and shrinks down to size “chunk” as the calculation proceeds.

�schedule(runtime)

– Schedule and chunk size taken from the OMP_SCHEDULE environment variable.

22

Schedule Clause When To Use

STATIC Pre-determined and predictable by the programmer

DYNAMIC Unpredictable, highly variable work per iteration

GUIDED Special case of dynamic to reduce scheduling overhead

The OpenMP APIThe OpenMP API

The schedule clauseThe schedule clause

Least work at runtime : scheduling done at compile-time

Least work at runtime : scheduling done at compile-time

Most work at runtime : complex scheduling logic used at run-time

Most work at runtime : complex scheduling logic used at run-time

Page 12: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 12

23

OpenMP: Work-Sharing Constructs

� The Sections work-sharing construct gives a different structured block to each thread.

#pragma omp parallel#pragma omp sections{#pragma omp section

X_calculation();#pragma omp section

y_calculation();#pragma omp section

z_calculation();}

#pragma omp parallel#pragma omp sections{#pragma omp section

X_calculation();#pragma omp section

y_calculation();#pragma omp section

z_calculation();}

By default, there is a barrier at the end of the “omp sections”. Use the “nowait” clause to turn off the barrier.

24

OpenMP: Work-Sharing Constructs

� The master construct denotes a structured block that is only executed by the master thread. The other threads just skip it (no synchronization is implied).

#pragma omp parallel private (tmp){

do_many_things();#pragma omp master

{ exchange_boundaries(); }#pragma barrier

do_many_other_things();

}

Page 13: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 13

25

OpenMP: Work-Sharing Constructs

� The single construct denotes a block of code that is executed by only one thread.

� A barrier is implied at the end of the single block.

#pragma omp parallel private (tmp){

do_many_things();#pragma omp single

{ exchange_boundaries(); }do_many_other_things();

}

26

The OpenMP* API

Combined parallel/work-share

� OpenMP* shortcut: Put the “parallel” and the work-share on the same line

double res[MAX]; int i;

#pragma omp parallel

{

#pragma omp for

for (i=0;i< MAX; i++) {

res[i] = huge();

}

}

These are equivalent

double res[MAX]; int i;

#pragma omp parallel for

for (i=0;i< MAX; i++) {

res[i] = huge();

}

� There’s also a “parallel sections” construct.

Page 14: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 14

27

Agenda

� Parallel computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

28

Data Environment:Default storage attributes

� Shared Memory programming model: – Most variables are shared by default

� Global variables are SHARED among threads– Fortran: COMMON blocks, SAVE variables, MODULE

variables

– C: File scope variables, static

� But not everything is shared...– Stack variables in sub-programs called from parallel regions

are PRIVATE

– Automatic variables within a statement block are PRIVATE.

Page 15: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 15

29

program sort

common /input/ A(10)

integer index(10)

!$OMP PARALLEL

call work(index)

!$OMP END PARALLEL

print*, index(1)

subroutine work (index)

common /input/ A(10)

integer index(*)

real temp(10)

integer count

save count

SSSS

Data Sharing Examples

temptemptemptemp

A, index, countA, index, countA, index, countA, index, count

temptemptemptemp temptemptemptemp

A, index, countA, index, countA, index, countA, index, count

A, index and count are shared by all threads.

temp is local to each

thread

A, index and count are shared by all threads.

temp is local to each

thread

* Third party trademarks and names are the property of their respective owner.

30

Data Environment:Changing storage attributes

� One can selectively change storage attributes constructs using the following clauses*

– SHARED

– PRIVATE

– FIRSTPRIVATE

– THREADPRIVATE

� The value of a private inside a parallel loop can be transmitted to a global value outside the loop with:

– LASTPRIVATE

� The default status can be modified with:

– DEFAULT (PRIVATE | SHARED | NONE)

All the clauses on this page apply to OpenMP construct NOT to the entire region.

All the clauses on this page apply to OpenMP construct NOT to the entire region.

All data clauses apply to parallel regions and worksharing constructs except “shared” which only applies to parallel regions.

Page 16: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 16

31

Private Clause

program wrongprogram wrongprogram wrongprogram wrong

IS = 0IS = 0IS = 0IS = 0

C$OMP PARALLEL DO PRIVATE(IS)C$OMP PARALLEL DO PRIVATE(IS)C$OMP PARALLEL DO PRIVATE(IS)C$OMP PARALLEL DO PRIVATE(IS)

DO J=1,1000 DO J=1,1000 DO J=1,1000 DO J=1,1000

IS = IS + JIS = IS + JIS = IS + JIS = IS + J

END DO END DO END DO END DO

print *, ISprint *, ISprint *, ISprint *, IS

� private(var) creates a local copy of var for each thread.

– The value is uninitialized

– Private copy is not storage-associated with the original

– The original is undefined at the end

IS was not initialized

Regardless of initialization, IS is undefined at this point

32

Firstprivate Clause

� Firstprivate is a special case of private.

– Initializes each private copy with the corresponding value from the master thread.

Regardless of initialization, IS is undefined at this point

program almost_rightprogram almost_rightprogram almost_rightprogram almost_right

IS = 0IS = 0IS = 0IS = 0

C$OMP PARALLEL DO FIRSTPRIVATE(IS)C$OMP PARALLEL DO FIRSTPRIVATE(IS)C$OMP PARALLEL DO FIRSTPRIVATE(IS)C$OMP PARALLEL DO FIRSTPRIVATE(IS)

DO J=1,1000 DO J=1,1000 DO J=1,1000 DO J=1,1000

IS = IS + JIS = IS + JIS = IS + JIS = IS + J

1000 CONTINUE 1000 CONTINUE 1000 CONTINUE 1000 CONTINUE

print *, ISprint *, ISprint *, ISprint *, IS

Each thread gets its own IS with an initial value of 0

Page 17: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 17

33

Lastprivate Clause

� Lastprivate passes the value of a private from the last iteration to a global variable.

IS is defined as its value at the “last sequential” iteration (i.e. for J=1000)

program closerprogram closerprogram closerprogram closer

IS = 0IS = 0IS = 0IS = 0

C$OMP PARALLEL DO FIRSTPRIVATE(IS) C$OMP PARALLEL DO FIRSTPRIVATE(IS) C$OMP PARALLEL DO FIRSTPRIVATE(IS) C$OMP PARALLEL DO FIRSTPRIVATE(IS)

C$OMP+ LASTPRIVATE(IS)C$OMP+ LASTPRIVATE(IS)C$OMP+ LASTPRIVATE(IS)C$OMP+ LASTPRIVATE(IS)

DO J=1,1000 DO J=1,1000 DO J=1,1000 DO J=1,1000

IS = IS + JIS = IS + JIS = IS + JIS = IS + J

1000 CONTINUE 1000 CONTINUE 1000 CONTINUE 1000 CONTINUE

print *, ISprint *, ISprint *, ISprint *, IS

Each thread gets its own IS with an initial value of 0

34

OpenMP: A data environment test� Consider this example of PRIVATE and FIRSTPRIVATE

� Are A,B,C local to each thread or shared inside the parallel region?

� What are their initial values inside and after the parallel region?

variables A,B, and C = 1

C$OMP PARALLEL PRIVATE(B)

C$OMP& FIRSTPRIVATE(C)

Inside this parallel region ...

� “A” is shared by all threads; equals 1

� “B” and “C” are local to each thread.

– B’s initial value is undefined

– C’s initial value equals 1

Outside this parallel region ...

� The values of “B” and “C” are undefined.

Page 18: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 18

35

OpenMP: Reduction

� Combines an accumulation operation across threads:

reduction (op : list)

� Inside a parallel or a work-sharing construct:

– A local copy of each list variable is made and initialized depending on the “op” (e.g. 0 for “+”).

– Compiler finds standard reduction expressions containing “op” and uses them to update the local copy.

– Local copies are reduced into a single value and combined with the original global value.

� The variables in “list” must be shared in the enclosing parallel region.

36

OpenMP: Reduction example� Remember the code we used to demo private,

firstprivate and lastprivate.

program closerprogram closerprogram closerprogram closer

IS = 0IS = 0IS = 0IS = 0

DO J=1,1000 DO J=1,1000 DO J=1,1000 DO J=1,1000

IS = IS + JIS = IS + JIS = IS + JIS = IS + J

1000 CONTINUE 1000 CONTINUE 1000 CONTINUE 1000 CONTINUE

print *, ISprint *, ISprint *, ISprint *, IS

� Here is the correct way to parallelize this code.

program closerprogram closerprogram closerprogram closer

IS = 0IS = 0IS = 0IS = 0

#pragma omp parallel for reduction(+:IS)#pragma omp parallel for reduction(+:IS)#pragma omp parallel for reduction(+:IS)#pragma omp parallel for reduction(+:IS)

DO J=1,1000 DO J=1,1000 DO J=1,1000 DO J=1,1000

IS = IS + JIS = IS + JIS = IS + JIS = IS + J

1000 CONTINUE 1000 CONTINUE 1000 CONTINUE 1000 CONTINUE

print *, ISprint *, ISprint *, ISprint *, IS

Page 19: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 19

37

OpenMP:Reduction operands/initial-values

� A range of associative operands can be used with reduction:

� Initial values are the ones that make sense mathematically.

Operand Initial value

+ 0

* 1

- 0

.AND. .true.

.OR. .false.

.NEQV. .false.

.EQV. .true.

MIN* Largest pos. number

MAX* Most neg. number

Operand Initial value

iand All bits on

ior 0

ieor 0

& ~0

| 0

^ 0

&& 1

|| 0

* Min and Max are not available in C/C++* Min and Max are not available in C/C++* Min and Max are not available in C/C++* Min and Max are not available in C/C++

38

Default Clause

� Note that the default storage attribute is DEFAULT(SHARED) (so no need to use it)

� To change default: DEFAULT(PRIVATE)

�each variable in static extent of the parallel region is made private as if specified in a private clause

�mostly saves typing

� DEFAULT(NONE): no default for variables in static extent. Must list storage attribute for each variable in static extent

Only the Fortran API supports default(private).

C/C++ only has default(shared) or default(none).

Page 20: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 20

39

Default Clause Example

itotal = 1000

C$OMP PARALLEL DEFAULT(PRIVATE) SHARED(itotal)

np = omp_get_num_threads()

each = itotal/np

SSS

C$OMP END PARALLEL

itotal = 1000

C$OMP PARALLEL PRIVATE(np, each)

np = omp_get_num_threads()

each = itotal/np

SSS

C$OMP END PARALLEL

Are these two codes equivalent?

yesyesyesyes

40

Agenda

� Parallel computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

Page 21: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 21

41

OpenMP: Synchronization

� High level synchronization:

– critical

– atomic

– barrier

– ordered

� Low level synchronization

– flush

– locks (both simple and nested)

42

The OpenMP* API

Synchronization – critical (in C/C++)

� Only one thread at a time can enter a criticalregion.

float res;

#pragma omp parallel

{ float B; int i;

#pragma omp forfor(i=0;i<niters;i++){

B = big_job(i);

#pragma omp criticalconsume (B, RES);

}}

Threads wait their turn –only one at a time calls consume()

Threads wait their turn –only one at a time calls consume()

* The mark “OpenMP” is the property of the OpenMP Architecture Review Board.

Page 22: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 22

43

OpenMP: Synchronization

� Atomic provides mutual exclusion execution but only applies to the update of a memory location (the update of X in the following example)

C$OMP PARALLEL PRIVATE(B) B = DOIT(I)tmp = big_ugly();

C$OMP ATOMICX = X + temp

C$OMP END PARALLEL

44

OpenMP: Synchronization

� Barrier: Each thread waits until all threads arrive.

#pragma omp parallel shared (A, B, C) private(id){

id=omp_get_thread_num();A[id] = big_calc1(id);

#pragma omp barrier#pragma omp for

for(i=0;i<N;i++){C[i]=big_calc3(I,A);}#pragma omp for nowait

for(i=0;i<N;i++){ B[i]=big_calc2(C, i); }A[id] = big_calc3(id);

}implicit barrier at the end of a parallel regionimplicit barrier at the end of a parallel region

implicit barrier at the end of a for work-sharing construct

implicit barrier at the end of a for work-sharing construct

no implicit barrier due to nowaitno implicit barrier due to nowait

Page 23: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 23

45

OpenMP: Synchronization

� The ordered region executes in the sequential order.

#pragma omp parallel private (tmp)#pragma omp for ordered

for (I=0;I<N;I++){tmp = NEAT_STUFF(I);

#pragma orderedres += consum(tmp);

}

46

OpenMP:Implicit synchronization

� Barriers are implied on the following OpenMP constructs:

end parallelend do (except when nowait is used)end sections (except when nowait is used) end single (except when nowait is used)

end parallelend do (except when nowait is used)end sections (except when nowait is used) end single (except when nowait is used)

Page 24: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 24

47

Agenda

� Parallel computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

�Recapitulation

48

OpenMP: Library routines:

� Runtime environment routines:

– Modify/Check the number of threads

– omp_set_num_threads(), omp_get_num_threads(), omp_get_thread_num(), omp_get_max_threads()

– Are we in a parallel region?

– omp_in_parallel()

– How many processors in the system?

– omp_num_procs()

…plus several less commonly used routines.…plus several less commonly used routines.…plus several less commonly used routines.…plus several less commonly used routines.

Page 25: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 25

49

OpenMP: Library Routines

� To use a known, fixed number of threads used in a program, (1) tell the system that you don’t want dynamic adjustment of the number of threads, (2) set the number threads, then (3) save the number you got.

#include <omp.h>void main(){ int num_threads;

omp_set_dynamic( 0 );omp_set_num_threads( omp_num_procs() );

#pragma omp parallel{ int id=omp_get_thread_num();

#pragma omp single num_threads = omp_get_num_threads();

do_lots_of_stuff(id); }

}

Protect this op since Memory stores are not atomic

Request as many threads as you have processors.

Disable dynamic adjustment of the number of threads.

Even in this case, the system may give you fewer threads Even in this case, the system may give you fewer threads Even in this case, the system may give you fewer threads Even in this case, the system may give you fewer threads than requested. If the precise # of threads matters, test than requested. If the precise # of threads matters, test than requested. If the precise # of threads matters, test than requested. If the precise # of threads matters, test for it and respond accordingly.for it and respond accordingly.for it and respond accordingly.for it and respond accordingly.

50

OpenMP: Environment Variables:

� Control how “omp for schedule(RUNTIME)” loop iterations are scheduled.

– OMP_SCHEDULE “schedule[, chunk_size]”

� Set the default number of threads to use.– OMP_NUM_THREADS int_literal

… … … … Plus several less commonly used environment variables.Plus several less commonly used environment variables.Plus several less commonly used environment variables.Plus several less commonly used environment variables.

Page 26: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 26

51

Agenda

� Parallel Computing, threads, and OpenMP

� The core elements of OpenMP�Thread creation

�Workshare constructs

�Managing the data environment

�Synchronization

�The runtime library and environment variables

� recapitulation

52

Let’s pause for a quick recap by example: Numerical Integration

∫4.0

(1+x2)dx = π

0

1

∑∑∑∑ F(xi)∆x ≈≈≈≈ ππππi = 0

N

Mathematically, we know that:

We can approximate the integral as a sum of rectangles:

Where each rectangle has width ∆x and height F(xi) at the middle of interval i.

4.0

2.0

1.0

X0.0

Page 27: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 27

53

PI Program: an example

static long num_steps = 100000;double step;void main (){ int i; double x, pi, sum = 0.0;

step = 1.0/(double) num_steps;

for (i=0;i<= num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);

}pi = step * sum;

}}

54

#include <omp.h>static long num_steps = 100000; double step;#define NUM_THREADS 2void main (){ int i, id, nthreads; double x, pi, sum[NUM_THREADS];

step = 1.0/(double) num_steps;omp_set_num_threads(NUM_THREADS);

#pragma omp parallel private (i, id, x){

id = omp_get_thread_num();#pragma omp singlenthreads = omp_get_num_threads();for (i=id, sum[id]=0.0;i< num_steps; i=i+nthreads){

x = (i+0.5)*step;sum[id] += 4.0/(1.0+x*x);

}}

for(i=0, pi=0.0;i<nthreads;i++)pi += sum[i] * step;}

OpenMP recap: Parallel Region

You canYou canYou canYou can’t assume that t assume that t assume that t assume that youyouyouyou’ll get the number of ll get the number of ll get the number of ll get the number of threads you requested.threads you requested.threads you requested.threads you requested.

Prevent write conflicts with Prevent write conflicts with Prevent write conflicts with Prevent write conflicts with the single.the single.the single.the single.

Performance will suffer due to false sharing of the sum array.

Performance will suffer due to false sharing of the sum array.

Promote scalar to an array Promote scalar to an array Promote scalar to an array Promote scalar to an array dimensioned by number of dimensioned by number of dimensioned by number of dimensioned by number of threads to avoid race threads to avoid race threads to avoid race threads to avoid race condition.condition.condition.condition.

Page 28: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 28

55

#include <omp.h>static long num_steps = 100000; double step;#define NUM_THREADS 2void main (){ int i, id, nthreads; double x, pi, sum;

step = 1.0/(double) num_steps;omp_set_num_threads(NUM_THREADS);

#pragma omp parallel private (i, id, x, sum){

id = omp_get_thread_num();#pragma omp single

nthreads = omp_get_num_threads();for (i=id, sum=0.0;i< num_steps; i=i+nthreads){

x = (i+0.5)*step;sum += 4.0/(1.0+x*x);

}#pragma omp critical

pi += sum * step;}}

OpenMP recap: Synchronization (critical region)

Note: this method of combining partial sums doesn’t scale very well.

Note: this method of combining partial sums doesn’t scale very well.

No array, so no false sharing.

No array, so no false sharing.

56

OpenMP recap : Parallel for with a reduction

#include <omp.h>

static long num_steps = 100000; double step;

#define NUM_THREADS 2

void main ()

{ int i; double x, pi, sum = 0.0;

step = 1.0/(double) num_steps;

omp_set_num_threads(NUM_THREADS);

#pragma omp parallel for private(x) reduction(+:sum)

for (i=0;i<= num_steps; i++){

x = (i+0.5)*step;

sum = sum + 4.0/(1.0+x*x);

}

pi = step * sum;

}

Note: we created a parallel program without changing any code and by adding 4

simple lines!

i private by i private by i private by i private by defaultdefaultdefaultdefault

For good OpenMP implementations, reduction is more

scalable than critical.

Page 29: OpenMP in Actiongabriel/courses/cosc4397_s10/ParCo_16_OpenMP.pdf · #pragma omp parallel #pragma omp sections {#pragma omp section X_calculation(); #pragma omp section y_calculation();

OpenMP Tutorial

The OpenMP API for Multithreaded Programming 29

57

OpenMP recap : Use environment variables to set number of threads

#include <omp.h>

static long num_steps = 100000; double step;

void main ()

{ int i; double x, pi, sum = 0.0;

step = 1.0/(double) num_steps;

#pragma omp parallel for private(x) reduction(+:sum)

for (i=0;i<= num_steps; i++){

x = (i+0.5)*step;

sum = sum + 4.0/(1.0+x*x);

}

pi = step * sum;

}

In practice, you set number of threads by

setting the environment variable,

OMP_NUM_THREADS