Вы находитесь на странице: 1из 78

..

OpenMP


2009

..
-

..



OpenMP


2009

681.3.06
22.20
72
:
. , - .. ,
. - , .. .

..
72

OpenMP: . .: - , 2009. 77 .
ISBN 978-5-211-05702-9
OpenMP.
OpenMP
. , OpenMP 3.0 , , .
.
OpenMP .
,

http://parallel.ru/tech/tech_dev/OpenMP/examples/. , .
, , .

681.3.06
22.20

ISBN 978-5-211-05702-9

.., 2009
, 2009


, ,
OpenMP................................................................................................. 4
............................................................................................................. 4
.................................................................................................................... 4
................................................................................................................ 4
...................................................................................... 5
................................................................................................................... 6
................................................................................................... 8
...................................................................................... 8
..................................................................... 9
....................................................................................... 10
.................................................................................... 11
.................................................................................................... 11
................................................................................................................ 12
...................................................... 14
parallel ....................................................................................... 14
.......................................................................................... 17
.......................................... 17
single............................................................................................ 24
master............................................................................................ 27
................................................................................................................ 28
...................................................................................................... 29
................................................................................................................ 35
.......................................................................................... 36
............................................................... 36
......................................................................................... 37
........................................................................................ 47
workshare..................................................................................... 52
(tasks) .................................................................................................. 53
................................................................................................................ 54
...................................................................................................... 55
.................................................................................................................. 55
ordered ......................................................................................... 56
.......................................................................................... 57
atomic............................................................................................ 59
67 ................................................................................................................... 61
flush .............................................................................................. 66
................................................................................................................ 66
............................................... 68
OpenMP ....................................................................................... 71
............................................................................................... 73
............................................................................................................. 76
3

, , OpenMP

atomic
barrier
critical
do
end critical
end do
end master
end parallel
end sections
end single
flush
for
master
ordered
parallel
section
sections
single
task
taskwait
threadprivate

59,
55
57,
38,
57,
38,
27,
14,
48,
24,
66
38,
27
56
14,
48,
47,
24,
53
54
33

omp_destroy_lock
62,
63, 64
omp_destroy_nest_lock
62
omp_get_active_level
69
omp_get_ancestor_thread_num
68
omp_get_dynamic
19
omp_get_level
68
omp_get_max_active_levels
68
omp_get_max_threads
20
omp_get_nested
23
omp_get_num_procs
20
omp_get_num_threads
36
omp_get_schedule
47
omp_get_team_size
69
omp_get_thread_limit
70
omp_get_thread_num
36
omp_get_wtick
12
omp_get_wtime
11
omp_in_parallel
23
omp_init_lock
61,
63, 64
omp_init_nest_lock
61
omp_set_dynamic
19
omp_set_lock
62,
63
omp_set_max_active_levels
68
omp_set_nest_lock
62
omp_set_nested
21
omp_set_num_threads
17
omp_set_schedule
46
omp_test_lock
64
omp_test_nest_lock
64
omp_unset_lock
62,
63, 64
omp_unset_nest_lock
62

60
58
41, 43, 44
59
41, 43, 44
28
15, 16
49
26
40, 42, 44

15, 16
49
48, 49
25, 26

collapse
copyin
copyprivate
default
firstprivate
48, 53
if
lastprivate
nowait
num_threads
ordered
private
48, 53
reduction
schedule
shared
untied

38
15,
24,
14,
15,

35
26
53
24, 32, 38,

14,
38,
25,
14,
39,
14,

53
48, 50
39, 48, 52
17
56
24, 29, 38,

15, 16, 38, 48


38, 41, 42, 44
15, 29, 30, 53
53


OMP_DYNAMIC
OMP_MAX_ACTIVE_LEVELS
OMP_NESTED
OMP_NUM_THREADS
OMP_SCHEDULE
OMP_STACKSIZE
OMP_THREAD_LIMIT
OMP_WAIT_POLICY

18
68
21
11
42
69
70
70



, , OpenMP. ,
, . ,
, OpenMP API.
OpenMP ,
.
, .
, - .
OpenMP
ARB (Architecture Review Board) [1], SMP- . OpenMP /C++.
1997 , /C++ 1998 . OpenMP 3.0 [3] (
2008 ).
OpenMP SMP- (SSMP, ccNUMA )
(shared memory model). OpenMP , .
OpenMP ,
(master) (slave) , . , ,
.
POSIX- (Pthreads) UNIX-,
:
, , 6

,
. OpenMP Pthreads (
); OpenMP ,
Pthreads, , , , .
POSIX threads, UNIX- , ,
. . ,
, LWP (light-weight processes).
OpenMP , , , ,
. ,
.
, .
OpenMP
.

..
[9] Intel Fortran/C++ 11.0.
OpenMP -
Parallel.ru [4].



OpenMP
, OpenMP,
(, icc/ifort openmp, gcc
/gfortran fopenmp, Sun Studio -xopenmp, Visual C++ - /openmp, PGI -mp).
OpenMP
. , OpenMP, OpenMP .
OpenMP _OPENMP,
, . yyyymm, yyyy mm , OpenMP. , ,
OpenMP 3.0, _OPENMP 200805.
, -
OpenMP, #ifdef
#ifndef. 1.
#include <stdio.h>
int main(){
#ifdef _OPENMP
printf("OpenMP is supported!\n");
#endif
}

1a. .
program example1b
#ifdef _OPENMP
print *, "OpenMP is supported!"
#endif
end

1b. .
!$, C$ *$. , OpenMP, ,
. 1 .

!$

program example1c
print *, "OpenMP is supported!"
end

1c. .

OpenMP
, . OpenMP SPMD- (Single Program Multiple Data) ,
.

(), ,
. , (), , .
.
,
. , ,
.
,
, ,
. ,
OpenMP.

. , , .
OpenMP
.
OpenMP
. , .
.


OpenMP . ,
. OpenMP

!$OMP, C$OMP *$OMP,
, #pragma omp. omp ,
OpenMP .
/++:
#pragma omp directive-name [[[,] ]...]

:
!$OMP directive-name [[[,] ]...]
$OMP directive-name [[[,] ]...]
*$OMP directive-name [[[,] ]...]

,
.
OpenMP . . ,
. ( COMMON-, ),
.
OpenMP 3 : , , . (clause). ,
.
OpenMP ( ), omp.h
( omp_lib.h omp_lib).
OpenMP-,
.
.

10

, OpenMP, omp_.
, , OpenMP .
, ,
. OpenMP .
, OpenMP, , , (stub). , Intel
openmp-stubs.

. , ,
OMP_NUM_THREADS. , Linux bash :
export OMP_NUM_THREADS=n

,
. .

OpenMP .
omp_get_wtime()
( ), .
:
double omp_get_wtime(void);

:
double precision function omp_get_wtime()

,
.
, , ,

11

.
.
omp_get_wtick() . .
:
double omp_get_wtick(void);

:
double precision function omp_get_wtick()

omp_get_wtime()
omp_get_wtick() OpenMP.
, . . ,
.
2

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
double start_time, end_time, tick;
start_time = omp_get_wtime();
end_time = omp_get_wtime();
tick = omp_get_wtick();
printf(" %lf\n", end_time-start_time);
printf(" %lf\n", tick);
}

2a. .
program example2b
include "omp_lib.h"
double precision start_time, end_time, tick
start_time = omp_get_wtime()
end_time = omp_get_wtime()
tick = omp_get_wtick()
print *, " ", end_time-start_time
print *, " ", tick
end

2b. .

, OpenMP .

OpenMP
12

.
?
OpenMP ? ?
- ?
OpenMP , omp_get_wtick().
?

13


-
, .
. .
parallel
parallel (parallel
... end parallel).
:
#pragma omp parallel [[[,] ]...]

:
!$omp parallel [[[,] ]...]
< >
!$omp end parallel

:
if() .
. , ;
num_threads ( ) , ; ,
omp_set_num_threads(),

OMP_NUM_THREADS;
default(private|firstprivate|shared|none)
, ,
private, firstprivate shared ; none ,
; shared none;
private() , ;
;

14

firstprivate() , ; -;
shared() , ;
copyin() ,
threadprivate, -;
reduction(:) ; ;
( 0 , 1 );

; : +, *, -,
&, |, ^, &&, ||, +, *, -, .and., .or., .eqv., .neqv.,
max, min, iand, ior, ieor; , .
OMP_NUM_THREADS-1
, ,
0 ().
1
OMP_NUM_THREADS-1. , , . , .
, . , SMP- ( , , ).
3 parallel.
- " 1",
parallel ,
" ", - " 2".

15

#include <stdio.h>
int main(int argc, char *argv[])
{
printf(" 1\n");
#pragma omp parallel
{
printf(" \n");
}
printf(" 2\n");
}

3a. .
program example3b
print *, " 1"
!$omp parallel
print *, " "
!$omp end parallel
print *, " 2"
end

3b. .
4 reduction.
.
count 0. ,
count
.
count , count .
#include <stdio.h>
int main(int argc, char *argv[])
{
int count = 0;
#pragma omp parallel reduction (+: count)
{
count++;
printf(" count: %d\n", count);
}
printf(" : %d\n", count);
}

4a. reduction .

16

program example4b
integer count
count=0
!$omp parallel reduction (+: count)
count=count+1
print *, " count: ", count
!$omp end parallel
print *, " : ", count
end

4b. reduction .


, sections workshare, : parallel for (parallel do ), parallel sections parallel workshare. , nowait.

,
, ,
OMP_NUM_THREADS. , Linux bash
:
export OMP_NUM_THREADS=n

OMP_NUM_THREADS .
omp_set_num_threads().
:
void omp_set_num_threads(int num);

:
subroutine omp_set_num_threads(num)
integer num

5 omp_set_num_threads()
num_threads.
omp_set_num_threads(2) , 2.
num_threads(3),
, . , " 1" . num_threads , 17

omp_set_num_threads(2), " 2"


.
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
omp_set_num_threads(2);
#pragma omp parallel num_threads(3)
{
printf(" 1\n");
}
#pragma omp parallel
{
printf(" 2\n");
}
}

5a. omp_set_num_threads() num_threads .

!$omp
!$omp
!$omp
!$omp

program example5b
include "omp_lib.h"
call omp_set_num_threads(2);
parallel num_threads(3)
print *, " 1"
end parallel
parallel
print *, " 2"
end parallel
end

5b. omp_set_num_threads() num_threads


.
, , , . , OMP_DYNAMIC true. , Linux
bash :
export OMP_DYNAMIC=true

, : false.

OMP_DYNAMIC
omp_set_dynamic().

18

:
void omp_set_dynamic(int num);

:
subroutine omp_set_dynamic(num)
logical num

omp_set_dynamic() 0 1, .FALSE. .TRUE.


,
omp_set_dynamic() OMP_DYNAMIC .
OMP_DYNAMIC
omp_get_dynamic().
:
int omp_get_dynamic(void);

:
logical function omp_get_dynamic()

6 omp_set_dynamic()
omp_get_dynamic(). , omp_get_dynamic()
OMP_DYNAMIC

omp_set_dynamic() OMP_DYNAMIC true,


omp_get_dynamic().
, (128). . master
-.
(128).

19

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
printf(" OMP_DYNAMIC: %d\n", omp_get_dynamic());
omp_set_dynamic(1);
printf(" OMP_DYNAMIC: %d\n", omp_get_dynamic());
#pragma omp parallel num_threads(128)
{
#pragma omp master
{
printf(" , %d \n",
omp_get_num_threads());
}
}
}

6a. omp_set_dynamic() omp_get_dynamic() .


program example6b
include "omp_lib.h"
print *, " OMP_DYNAMIC: ", omp_get_dynamic()
call omp_set_dynamic(.TRUE.)
print *, " OMP_DYNAMIC: ", omp_get_dynamic()
!$omp parallel num_threads(128)
!$omp master
print *, " ,", omp_get_num_threads(),
&
" "
!$omp end master
!$omp end parallel
end

6b. omp_set_dynamic() omp_get_dynamic() .


omp_get_max_threads() .
:
int omp_get_max_threads(void);

:
integer function omp_get_max_threads()

omp_get_num_procs() , . ,
.
:
int omp_get_num_procs(void);

20

:
integer function omp_get_num_procs()

;
. OMP_NESTED. , Linux
bash :
export OMP_NESTED=true

OMP_NESTED omp_set_nested().
:
void omp_set_nested(int nested)

:
subroutine omp_set_nested(nested)
logical nested

omp_set_nested() . 0 1,
.FALSE. .TRUE. ,
, ,
. -. , .
7
omp_set_nested(). omp_set_nested()
.

omp_get_thread_num(). ,
. omp_set_nested() .

, .

21

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n;
omp_set_nested(1);
#pragma omp parallel private(n)
{
n=omp_get_thread_num();
#pragma omp parallel
{
printf(" 1, %d - %d\n", n,
omp_get_thread_num());
}
}
omp_set_nested(0);
#pragma omp parallel private(n)
{
n=omp_get_thread_num();
#pragma omp parallel
{
printf(" 2, %d - %d\n", n,
omp_get_thread_num());
}
}
}

7a. .
program example7b
include "omp_lib.h"
integer n
call omp_set_nested(.TRUE.)
!$omp parallel private(n)
n=omp_get_thread_num()
!$omp parallel
print *, " 1, ", n, " - ",
&
omp_get_thread_num()
!$omp end parallel
!$omp end parallel
call omp_set_nested(.FALSE.)
!$omp parallel private(n)
n=omp_get_thread_num()
!$omp parallel
print *, " 2, ", n, " - ",
&
omp_get_thread_num()
!$omp end parallel
!$omp end parallel
end

7b. .
OMP_NESTED
omp_get_nested().
22

:
int omp_get_nested(void);

:
logical function omp_get_nested()

omp_in_parallel() 1 (.TRUE. ), .
:
int omp_in_parallel(void);

:
logical function omp_in_parallel()

8 omp_in_parallel().
mode ,
. " ", " ".
#include <stdio.h>
#include <omp.h>
void mode(void){
if(omp_in_parallel()) printf(" \n");
else printf(" \n");
}
int main(int argc, char *argv[])
{
mode();
#pragma omp parallel
{
#pragma omp master
{
mode();
}
}
}

8a. omp_in_parallel() .

23

!$omp
!$omp
!$omp
!$omp

program example8b
call mode()
parallel
master
call mode()
end master
end parallel
end
subroutine mode()
include "omp_lib.h"
if(omp_in_parallel()) then
print *, " "
else
print *, " "
end if
end

8b. omp_in_parallel() .
single
- , single (single ...
end single).
:
#pragma omp single [ [[,] ]...]

:
!$omp single [ [[,] ]...]
< >
!$omp end single [ [[,] ]...]

:


private() , -

;
;


firstprivate() , -

; -;


copyprivate() , single,
(private firstprivate),


; nowait;
24

private
firstprivate single;


nowait

: ,
; ,
nowait , ,
.
single,
private firstprivate
single, copyprivate nowait end single.
,
. , ,
nowait. single .
9 single
nowait. " 1",
( -) "
". , single, " 2". ,
" 2" " ",
. nowait, single
, " 2"
" ".
#include <stdio.h>
int main(int argc, char *argv[])
{
#pragma omp parallel
{
printf(" 1\n");
#pragma omp single nowait
{
printf(" \n");
}
printf(" 2\n");
}
}

9a. single nowait .

25

!$omp
!$omp
!$omp
!$omp

program example9b
parallel
print *, " 1"
single
print *, " "
end single nowait
print *, " 2"
end parallel
end

9b. single nowait .


10 copyprivate. n .
n , ,
. single n 100,
n . n 100.
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n;
#pragma omp parallel private(n)
{
n=omp_get_thread_num();
printf(" n (): %d\n", n);
#pragma omp single copyprivate(n)
{
n=100;
}
printf(" n (): %d\n", n);
}
}

10a. copyprivate .

!$omp

!$omp
!$omp
!$omp

program example10b
include "omp_lib.h"
integer n
parallel private(n)
n=omp_get_thread_num()
print *, " n (): ", n
single
n=100;
end single copyprivate(n)
print *, " n (): ", n
end parallel
end

10b. copyprivate .
26

master
master (master ... end master) , -. ,
. .
:
#pragma omp master

:
!$omp master
< ->
!$omp end master

11 master. n , . n 1. - n 2, n. n 3, n. , master .
1, -
2, - 3.
#include <stdio.h>
int main(int argc, char *argv[])
{
int n;
#pragma omp parallel private(n)
{
n=1;
#pragma omp master
{
n=2;
}
printf(" n: %d\n", n);
#pragma omp barrier
#pragma omp master
{
n=3;
}
printf(" n: %d\n", n);
}
}

11a. master .

27

!$omp
!$omp
!$omp
!$omp
!$omp
!$omp
!$omp

program example11b
integer n
parallel private(n)
n=1
master
n=2
end master
print *, " n: ", n
barrier
master
n=3;
end master
print *, " n: ", n
end parallel
end

11b. master .

,
.
if parallel?
, , .
8 ( 2 ). , , .
single master?
- , single?
1 ,
master?

28


OpenMP
, .
OpenMP
:
shared (; );
private (, ;
).
.
( ) .
.


, (data race),
.
, , ,
(shared).
, , . , , (private).
default.
,
,
OpenMP private, shared, firstprivate, lastprivate, reduction.
12 private.
n .
, n,
n .
n . n , n
29

1. n
, . , omp_get_thread_num() n.
n, 1 (
).
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n=1;
printf("n (): %d\n", n);
#pragma omp parallel private(n)
{
printf(" n ( ): %d\n", n);
/* n */
n=omp_get_thread_num();
printf(" n ( ): %d\n", n);
}
printf("n (): %d\n", n);
}

12a. private .
program example12b
include "omp_lib.h"
integer n
n=1
print *, "n (): ", n
!$omp parallel private(n)
print *, " n ( ): ", n
C n
n=omp_get_thread_num()
print *, " n ( ): ", n
!$omp end parallel
print *, "n (): ", n
end

12b. private .
13 shared. m
. m .
,
, 1. , m.

30

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int i, m[10];
printf(" m :\n");
/* m */
for (i=0; i<10; i++){
m[i]=0;
printf("%d\n", m[i]);
}
#pragma omp parallel shared(m)
{
/* 1 m,
*/
m[omp_get_thread_num()]=1;
}
/* */
printf(" m :\n");
for (i=0; i<10; i++) printf("%d\n", m[i]);
}

13a. shared .
program example13b
include "omp_lib.h"
integer i, m(10)
print *, " m :"
C m
do i=1, 10
m(i)=0
print *, m(i)
end do
!$omp parallel shared(m)
C 1 m,
C
m(omp_get_thread_num()+1)=1
!$omp end parallel
C */
print *, " m :"
do i=1, 10
print *, m(i)
end do
end

13b. shared .
(static) ,
, (shared).
, , .

31

(shared)
COMMON-.

reduction, firstprivate, lastprivate, copyin.
14 firstprivate.
n firstprivate . n
. n
.
n ,
1. ,
omp_get_thread_num() n
n.
n, 1.
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n=1;
printf(" n : %d\n", n);
#pragma omp parallel firstprivate(n)
{
printf(" n ( ): %d\n", n);
/* n */
n=omp_get_thread_num();
printf(" n ( ): %d\n", n);
}
printf(" n : %d\n", n);
}

14a. firstprivate .
program example14b
include "omp_lib.h"
integer n
n=1
print *, " n : ", n
!$omp parallel firstprivate(n)
print *, " n ( ): ", n
C n
n=omp_get_thread_num()
print *, " n ( ): ", n
!$omp end parallel
print *, " n : ", n
end

14b. firstprivate .
32

threadprivate ,
, .
:
#pragma omp threadprivate()

:
!$omp threadprivate()

threadprivate
COMMON- , . , .
, ,
, ,
OMP_DYNAMIC false
. , threadprivate, OpenMP, copyin, copyprivate, schedule,
num_threads, if.
15 threadprivate. n threadprivate .
n . n ,
1 - 0 .
omp_get_thread_num() n
.
n,
-, 0. n ,
.

33

#include <stdio.h>
#include <omp.h>
int n;
#pragma omp threadprivate(n)
int main(int argc, char *argv[])
{
int num;
n=1;
#pragma omp parallel private (num)
{
num=omp_get_thread_num();
printf(" n %d ( ): %d\n", num, n);
/* n */
n=omp_get_thread_num();
printf(" n %d ( ): %d\n", num, n);
}
printf(" n (): %d\n", n);
#pragma omp parallel private (num)
{
num=omp_get_thread_num();
printf(" n %d ( ): %d\n", num, n);
}
}

15a. threadprivate .
program example15b
include "omp_lib.h"
common/nnn/n
integer n, num;
!$omp threadprivate(/nnn/)
n=1;
!$omp parallel private (num)
num=omp_get_thread_num()
print *, " n ", num, " ( ): ", n
C n
n=omp_get_thread_num();
print *, " n ", num, " ( ): ", n
!$omp end parallel
print *, " n (): ", n
!$omp parallel private (num)
num=omp_get_thread_num()
print *, " n ", num, " ( ): ", n
!$omp end parallel
end

15b. threadprivate .
, threadprivate, -,
copyin.
, threadprivate,
, 34

, copyprivate
single.
16 copyin. n threadprivate. copyin n -. n, 1.
#include <stdio.h>
int n;
#pragma omp threadprivate(n)
int main(int argc, char *argv[])
{
n=1;
#pragma omp parallel copyin(n)
{
printf(" n: %d\n", n);
}
}

16a. copyin .
program example16b
common/nnn/n
integer n
!$omp threadprivate(/nnn/)
n=1;
!$omp parallel copyin(n)
print *, " n: ", n
!$omp end parallel
end

16b. copyin .

, ?
, ?
,
?
?

? ,
?
copyin firstprivate?

35


OpenMP . OpenMP .


0 N-1, N , .
, omp_get_thread_num() omp_get_num_threads(),
, .
omp_get_thread_num() .
:
int omp_get_thread_num(void);

:
integer function omp_get_thread_num()

omp_get_num_threads() .
:
int omp_get_num_threads(void);

:
integer function omp_get_num_threads()

17 omp_get_num_threads()
omp_get_thread_num(). , 0, ,
.

36

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int count, num;
#pragma omp parallel
{
count=omp_get_num_threads();
num=omp_get_thread_num();
if (num == 0) printf(" : %d\n", count);
else printf(" %d\n", num);
}
}

17a. omp_get_num_threads() omp_get_thread_num() .


program example17b
include "omp_lib.h"
integer count, num
!$omp parallel
count=omp_get_num_threads()
num=omp_get_thread_num()
if (num .eq. 0) then
print *, " : ", count
else
print *, " ", num
end if
!$omp end parallel
end

17b. omp_get_num_threads() omp_get_thread_num() .


omp_get_thread_num() omp_get_num_threads()
,
MPI [8]. OpenMP
.
OpenMP .

, , , , .
for (do
... [end do]).
37

:
#pragma omp for [ [[,] ]...]

:
!$omp do [ [[,] ]...]
< do>
[!$omp end do [nowait]]

,
for (do).
:


private() , -

;
;


firstprivate() , -

; -;


lastprivate() , , -

;


reduction(:) -

; ;
( 0 , 1 );
; : +, *, -, &, |, ^, &&, ||,
+, *, -, .and., .or., .eqv., .neqv., max, min,
iand, ior, ieor; , ;


schedule(type[, chunk]) ,

;


collapse(n) , n -

; , ;
collapse , ;

38

ordered , , ordered; ,

,
;


nowait

: , ;
, nowait
, ,
. end do
, .
end do,
do.
. , , , . .
, schedule,
.

:
for([ ] i = ;
i {<,>,=,<=,>=} ;
i {+,-}= )

, OpenMP
.
, ,
.
, , ,
. ,
lastprivate.

39

18 for (do). A, B, C. . i n . n
. for (do)
, . i- i- A
B i- C. , .
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int A[10], B[10], C[10], i, n;
/* */
for (i=0; i<10; i++){ A[i]=i; B[i]=2*i; C[i]=0; }
#pragma omp parallel shared(A, B, C) private(i, n)
{
/* */
n=omp_get_thread_num();
#pragma omp for
for (i=0; i<10; i++)
{
C[i]=A[i]+B[i];
printf(" %d %d\n",
n, i);
}
}
}

18a. for .

40

program example18b
include "omp_lib.h"
integer A(10), B(10), C(10), i, n
C
do i=1, 10
A(i)=i
B(i)=2*i
C(i)=0
end do
!$omp parallel shared(A, B, C) private(i, n)
C
n=omp_get_thread_num()
!$omp do
do i=1, 10
C(i)=A(i)+B(i)
print *, " ", n, " ", i
end do
!$omp end parallel
end

18b. do .
schedule type :
static - ;
chunk. chunk
, .. , . chunk
,
( ), .
dynamic
: chunk (
chunk=1), ,
, chunk .
, .
, .
guided ,

chunk ( chunk=1)
, , .
.

41

. chunk.
auto
/ . chunk .
runtime
OMP_SCHEDULE.
chunk .
19 schedule
(static), (static, 1), (static, 2), (dynamic), (dynamic, 2), (guided),
(guided, 2). ,
.
, .
, .
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int i;
#pragma omp parallel private(i)
{
#pragma omp for schedule (static)
//#pragma omp for schedule (static, 1)
//#pragma omp for schedule (static, 2)
//#pragma omp for schedule (dynamic)
//#pragma omp for schedule (dynamic, 2)
//#pragma omp for schedule (guided)
//#pragma omp for schedule (guided, 2)
for (i=0; i<10; i++)
{
printf(" %d %d\n",
omp_get_thread_num(), i);
sleep(1);
}
}
}

19a. schedule .

42

program example19b
include "omp_lib.h"
integer i
!$omp parallel private(i)
!$omp do schedule (static)
C!$omp do schedule (static, 1)
C!$omp do schedule (static, 2)
C!$omp do schedule (dynamic)
C!$omp do schedule (dynamic, 2)
C!$omp do for schedule (guided)
C!$omp do for schedule (guided, 2)
do i=0, 9
print *, " ", omp_get_thread_num(),
&
" ", i
call sleep(1)
end do
!$omp end parallel
end

19b. schedule .
19
1.
, . , .
4 .
(dynamic, guided) .
static,
1

static,
2

dynamic

dynamic,
2

guided

guided,
2

0 0

1 0

2 0

3 1

4 1

5 1

6 2

7 2

8 3

9 3

static

1. .

43

1 .
(static, 2), (dynamic, 2) (guided, 2).
, .
.
20 schedule
(static, 6), (dynamic, 6), (guided, 6). ,
. , . , .
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int i;
#pragma omp parallel private(i)
{
#pragma omp for schedule (static, 6)
//#pragma omp for schedule (dynamic, 6)
//#pragma omp for schedule (guided, 6)
for (i=0; i<200; i++)
{
printf(" %d %d\n",
omp_get_thread_num(), i);
sleep(1);
}
}
}

20a. schedule .
program example20b
include "omp_lib.h"
integer i
!$omp parallel private(i)
!$omp do schedule (static, 6)
C!$omp do schedule (dynamic, 6)
C!$omp do schedule (guided, 6)
do i=0, 200
print *, " ", omp_get_thread_num(),
&
" ", i
call sleep(1)
end do
!$omp end parallel
end

20b. schedule .

44

20 for (. 1a . 1c).

.1a. (static, 6)

.1b. (dynamic, 6)

45

.1c. (guided, 6)
6
(static, 6),
(dynamic, 6) (guided, 6).
24 6 .
OMP_SCHEDULE .
,
runtime .
OMP_SCHEDULE Linux
bash :
export OMP_SCHEDULE="dynamic,1"

OMP_SCHEDULE omp_set_schedule().
:
void omp_set_schedule(omp_sched_t type, int chunk);

46

:
subroutine omp_set_schedule(type, chunk)
integer (kind=omp_sched_kind) type
integer chunk

omp.h (omp_lib.h).
, :
typedef enum omp_sched_t {
omp_sched_static = 1,
omp_sched_dynamic = 2,
omp_sched_guided = 3,
omp_sched_auto = 4
} omp_sched_t;

:
integer(kind=omp_sched_kind),
integer(kind=omp_sched_kind),
integer(kind=omp_sched_kind),
integer(kind=omp_sched_kind),

parameter
parameter
parameter
parameter

::
::
::
::

omp_sched_static = 1
omp_sched_dynamic = 2
omp_sched_guided = 3
omp_sched_auto = 4

omp_get_schedule() OMP_SCHEDULE.
:
void omp_get_schedule(omp_sched_t* type, int* chunk);

:
subroutine omp_get_schedule(type, chunk);
integer (kind=omp_sched_kind) type
integer chunk

,
[5].
, , . , .
, , , .

sections (sections ... end sections) () .
:
#pragma omp sections [ [[,] ]...]

47

:
!$omp sections [ [[,] ]...]
< >
!$omp end sections [nowait]

, .
:


private() , -

;
;


firstprivate() , -

; -;


lastprivate() , , -

, ;


reduction(:) -

; ;
( 0 , 1 );
; : +, *, -, &, |, ^, &&, ||,
+, *, -, .and., .or., .eqv., .neqv., max, min, iand, ior,
ieor; , ;


nowait -

:
, ;
, nowait ,
,
.
section sections .
:
#pragma omp section

48

:
!$omp section

sections section . , . ,
. , (
) .
21 sections. C , section,
, .
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n;
#pragma omp parallel private(n)
{
n=omp_get_thread_num();
#pragma omp sections
{
#pragma omp section
{
printf(" , %d\n", n);
}
#pragma omp section
{
printf(" , %d\n", n);
}
#pragma omp section
{
printf(" , %d\n", n);
}
}
printf(" , %d\n", n);
}
}

21a. sections .

49

!$omp
!$omp
!$omp
!$omp
!$omp
!$omp
!$omp

program example21b
include "omp_lib.h"
integer n
parallel private(n)
n=omp_get_thread_num()
sections
section
print *, " , ", n
section
print *, " , ", n
section
print *, " , ", n
end sections
print *, " , ", n
end parallel
end

21b. sections .
22 lastprivate.
lastprivate sections.
n lastprivate . , section, n . sections n ,
3. n
.

50

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n=0;
#pragma omp parallel
{
#pragma omp sections lastprivate(n)
{
#pragma omp section
{
n=1;
}
#pragma omp section
{
n=2;
}
#pragma omp section
{
n=3;
}
}
printf(" n %d: %d\n",
omp_get_thread_num(), n);
}
printf(" n : %d\n", n);
}

22a. lastprivate .
program example22b
include "omp_lib.h"
integer n
n=0
!$omp parallel
!$omp sections lastprivate(n)
!$omp section
n=1;
!$omp section
n=2;
!$omp section
n=3;
!$omp end sections
print *, " n ",
&
omp_get_thread_num(), ": ", n
!$omp end parallel
print *, " n : ", n
end

22b. lastprivate .

51

workshare
workshare ... end workshare () , .
!$omp workshare
< >
!$omp end workshare [nowait]

,
. : , FORALL,
WHERE, atomic, critical, parallel.
( ),
. , ,
, . . ,
nowait.
23 workshare.
, workshare, .
, ,
.

!$omp
!$omp

!$omp
!$omp

program example23
real a(10), b(10), c(10), d(10), e(10)
integer i
do i=1, 10
a(i) = i
b(i) = 2*i
end do
parallel shared(a, b, c, d, e)
workshare
c=a+b
d=b-a
e=c+2*d
end workshare
end parallel
print *, " : ", e
end

23. workshare.

52

(tasks)
task (task ... end task) .
:
#pragma omp task [ [[,] ]...]

:
!$omp task [ [[,] ]...]
< >
!$omp end task


.
.
,
.
:


if() -

; , ;


untied ,

; ,
;


default(private|firstprivate|shared|none)
, , private,
firstprivate shared ; none , -

; shared none;


private() , -

;
;


firstprivate() , -

; -;


shared() , .
53

taskwait.
:
#pragma omp taskwait

:
!$omp taskwait

, , ,
.

omp_get_thread_num() omp_get_num_threads()
?
for (do ... [end do])?

?
, ?
? , ?
chunk
guided?
sections (sections ... end sections) section?

, ?
?
, .
, .

54


OpenMP
.

OpenMP .
barrier.
:
#pragma omp barrier

:
!$omp barrier

, , , , , .
, , (task).
24 barrier. barrier . " 1" " 2"
, " 3"
.
#include <stdio.h>
#include <omp.h>
int main(int argc, char
{
#pragma omp parallel
{
printf("
printf("
#pragma omp barrier
printf("
}
}

*argv[])

1\n");
2\n");
3\n");

24a. barrier .

55

program example24b
include "omp_lib.h"
!$omp parallel
print *, " 1"
print *, " 2"
!$omp barrier
print *, " 3"
!$omp end parallel
end

24b. barrier .
ordered
ordered (ordered ... end ordered)
, ,
.
:
#pragma omp ordered

:
!$omp ordered
< >
!$omp end ordered

,
ordered. , , . , , ,
. , , .
25 ordered ordered.
for (do) ordered.
ordered, .
, .

56

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int i, n;
#pragma omp parallel private (i, n)
{
n=omp_get_thread_num();
#pragma omp for ordered
for (i=0; i<5; i++)
{
printf(" %d, %d\n", n, i);
#pragma omp ordered
{
printf("ordered: %d, %d\n", n, i);
}
}
}
}

25a. ordered ordered .

!$omp
!$omp

!$omp
!$omp
!$omp

program example25b
include "omp_lib.h"
integer i, n;
parallel private (i, n)
n=omp_get_thread_num();
do ordered
do i=0, 4
print *, " ", n, ", ", i
ordered
print *, "ordered: ", n, ", ", i
end ordered
end do
end parallel
end

25b. ordered ordered .



critical (critical ... end critical)
.
:
#pragma omp critical [(<__>)]

:
!$omp critical [()]
< >
!$omp end critical [()]

57


. - ,
, , ,
.
, .
, , .

. , , ,
. .
26 critical. n
, . n.
n .
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int n;
#pragma omp parallel
{
#pragma omp critical
{
n=omp_get_thread_num();
printf(" %d\n", n);
}
}
}

26a. critical .

58

!$omp
!$omp

!$omp
!$omp

program example26b
include "omp_lib.h"
integer n
parallel
critical
n=omp_get_thread_num()
print *, " ", n
end critical
end parallel
end

26b. critical .
26 critical, . critical , 0 OMP_NUM_THREADS-1. ,
, , n ,
. .
,
- . ,
, . , . ,
. , ,
, .
atomic

. , sum
sum=sum+expr
, .
atomic.
:
#pragma omp atomic

59

:
!$omp atomic


( ), , .
, , . , .
27 atomic.
. count. ,
, , atomic.
#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
int count = 0;
#pragma omp parallel
{
#pragma omp atomic
count++;
}
printf(" : %d\n", count);
}

27a. atomic .
program example27b
include "omp_lib.h"
integer count
count = 0
!$omp parallel
!$omp atomic
count=count+1
!$omp end parallel
print *, " : ", count
end

27b. atomic .

60

'(
OpenMP
(locks). ( ). .
: ,
.
.
. , , , .
: . , .
(nesting count). ,
,
.
, .
omp_init_lock() omp_init_nest_lock().
:
void omp_init_lock(omp_lock_t *lock);
void omp_init_nest_lock(omp_nest_lock_t *lock);

:
subroutine omp_init_lock(svar)
integer (kind=omp_lock_kind) svar
subroutine omp_init_nest_lock(nvar)
integer (kind=omp_nest_lock_kind) nvar

.
.
omp_destroy_lock() omp_destroy_nest_lock()
.

61

:
void omp_destroy_lock(omp_lock_t *lock);
void omp_destroy_nest_lock(omp_nest_lock_t *lock);

:
subroutine omp_destroy_lock(svar)
integer (kind=omp_lock_kind) svar
subroutine omp_destroy_nest_lock(nvar)
integer (kind=omp_nest_lock_kind) nvar

omp_set_nest_lock().
:

omp_set_lock()

void omp_set_lock(omp_lock_t *lock);


void omp_set_nest_lock(omp_nest_lock_t *lock);

:
subroutine omp_set_lock(svar)
integer (kind=omp_lock_kind) svar
subroutine omp_set_nest_lock(nvar)
integer (kind=omp_nest_lock_kind) nvar

, . .
, , .
omp_unset_lock()
omp_unset_nest_lock().
:
void omp_unset_lock(omp_lock_t *lock);
void omp_unset_nest_lock(omp_lock_t *lock);

:
subroutine omp_unset_lock(svar)
integer (kind=omp_lock_kind) svar
subroutine omp_unset_nest_lock(nvar)
integer (kind=omp_nest_lock_kind) nvar

, . . , . ,
, , .

62

28 . lock
.
omp_init_lock().
n
. omp_set_lock()
, , , ,
omp_unset_lock(). " ..." " ...",
.
omp_destroy_lock() lock.
#include <stdio.h>
#include <omp.h>
omp_lock_t lock;
int main(int argc, char *argv[])
{
int n;
omp_init_lock(&lock);
#pragma omp parallel private (n)
{
n=omp_get_thread_num();
omp_set_lock(&lock);
printf(" , %d\n", n);
sleep(5);
printf(" , %d\n", n);
omp_unset_lock(&lock);
}
omp_destroy_lock(&lock);
}

28a. .
program example27b
include "omp_lib.h"
integer (kind=omp_lock_kind) lock
integer n
call omp_init_lock(lock)
!$omp parallel private (n)
n=omp_get_thread_num()
call omp_set_lock(lock)
print *, " , ", n
call sleep(5)
print *, " , ", n
call omp_unset_lock(lock)
!$omp end parallel
call omp_destroy_lock(lock)
end

28b. .
63


omp_test_lock() omp_test_nest_lock().
:
int omp_test_lock(omp_lock_t *lock);
int omp_test_nest_lock(omp_lock_t *lock);

:
logical
integer
integer
integer

function omp_test_lock(svar)
(kind=omp_lock_kind) svar
function omp_test_nest_lock(nvar)
(kind=omp_lock_kind) nvar

. ,
1 ( .TRUE.),
. , 0 (
.FALSE.).
29
omp_test_lock(). lock . omp_init_lock().
n . omp_test_lock() .
,
" ...",
sleep(), . , ,
omp_unset_lock(). , , ,
. , "
..." " ...",

.
omp_destroy_lock() lock.

64

#include <stdio.h>
#include <omp.h>
int main(int argc, char *argv[])
{
omp_lock_t lock;
int n;
omp_init_lock(&lock);
#pragma omp parallel private (n)
{
n=omp_get_thread_num();
while (!omp_test_lock (&lock))
{
printf(" , %d\n", n);
sleep(2);
}
printf(" , %d\n", n);
sleep(5);
printf(" , %d\n", n);
omp_unset_lock(&lock);
}
omp_destroy_lock(&lock);
}

29a. omp_test_lock() .
program example29b
include "omp_lib.h"
integer (kind=omp_lock_kind) lock
integer n
call omp_init_lock(lock)
!$omp parallel private (n)
n=omp_get_thread_num()
do while (.not. omp_test_lock(lock))
print *, " , ", n
call sleep(2)
end do
print *, " , ", n
call sleep(5)
print *, " , ", n
call omp_unset_lock(lock)
!$omp end parallel
call omp_destroy_lock(lock)
end

29b. omp_test_lock() .
, .

65

flush

,
, .
flush.
:
#pragma omp flush [()]

:
!$omp flush [()]

,
( , ), - , ; , , ; - ,
..
, , , .
, , ,
.
.
flush barrier,
parallel, critical, ordered, , nowait, omp_set_lock(), omp_unset_lock(), omp_test_lock(),
omp_set_nest_lock(), omp_unset_nest_lock(), omp_test_nest_lock(),
, (task). , flush , ,
atomic. , flush
, master.

, , ?

?
66

atomic?
:
o ;
o .
.
flush?
.
.

67


OMP_MAX_ACTIVE_LEVELS . omp_set_max_active_levels().
:
void omp_set_max_active_levels(int max);

:
subroutine omp_set_max_active_levels(max)
integer max

max , . .
OMP_MAX_ACTIVE_LEVELS
omp_get_max_active_levels().
:
int omp_get_max_active_levels(void);

:
integer function omp_get_max_active_levels()

omp_get_level() .
:
int omp_get_level(void);

:
integer function omp_get_level()

0.
omp_get_ancestor_thread_num() , level, , .
:
int omp_get_ancestor_thread_num(int level);

:
integer function omp_get_ancestor_thread_num(level)
integer level
68

level , -1. level=0, 0, level=omp_get_level(),


omp_get_thread_num().
omp_get_team_size() level
,
.
:
int omp_get_team_size(int level);

:
integer function omp_get_team_size(level)
integer level

level , -1. level=0, 1, level=omp_get_level(),


omp_get_num_threads().
omp_get_active_level() ,
, .
:
int omp_get_active_level(void);

:
integer function omp_get_active_level()

0.
OMP_STACKSIZE
. size |
sizeB | sizeK | sizeM | sizeG, size ,
B, K, M, G , , , . , .

, .
, Linux bash
:
export OMP_STACKSIZE=2000K

69

OMP_WAIT_POLICY .
ACTIVE,
, PASSIVE
,
.
OMP_THREAD_LIMIT , .
, .

omp_get_thread_limit().
:
int omp_get_thread_limit(void);

:
integer function omp_get_thread_limit()

70

OpenMP
/
, . , . ,
,
, .
OpenMP , ,
(, ) .
, , , , .
,
, () , ,
, workshare .
, , . .
, - .
,
.
, .
,
.

. , (, , )
/ .
OpenMP .
.
71

. ,
.

OpenMP .
, , . , , , .
, OpenMP,
. ,
.
OpenMP ,
OpenMP (stubs), .
.
OpenMP (orphaned) . , . ,
, , .
OpenMP , , MPI. MPI
, OpenMP
.

72


30 .
.
#include <stdio.h>
double f(double y) {return(4.0/(1.0+y*y));}
int main()
{
double w, x, sum, pi;
int i;
int n = 1000000;
w = 1.0/n;
sum = 0.0;
#pragma omp parallel for private(x) shared(w)\
reduction(+:sum)
for(i=0; i < n; i++)
{
x = w*(i-0.5);
sum = sum + f(x);
}
pi = w*sum;
printf("pi = %f\n", pi);
}

30a. .
program compute_pi
parameter (n = 1000000)
integer i
double precision w, x, sum, pi, f, y
f(y) = 4.d0/(1.d0+y*y)
w = 1.0d0/n
sum = 0.0d0;
!$omp parallel do private(x) shared(w)
!$omp& reduction(+:sum)
do i=1,n
x = w*(i-0.5d0)
sum = sum + f(x)
end do
pi = w*sum
print *, 'pi = ', pi
end

30b. .

73

31 ,
. , .
i j .
#include <stdio.h>
#include <omp.h>
#define N 4096
double a[N][N], b[N][N], c[N][N];
int main()
{
int i, j, k;
double t1, t2;
//
for (i=0; i<N; i++)
for (j=0; j<N; j++)
a[i][j]=b[i][j]=i*j;
t1=omp_get_wtime();
//
#pragma omp parallel for shared(a, b, c) private(i, j, k)
for(i=0; i<N; i++){
for(j=0; j<N; j++){
c[i][j] = 0.0;
for(k=0; k<N; k++) c[i][j]+=a[i][k]*b[k][j];
}
}
t2=omp_get_wtime();
printf("Time=%lf\n", t2-t1);
}

31a. .

74

program matrmult
include "omp_lib.h"
integer N
parameter(N=4096)
common /arr/ a, b, c
double precision a(N, N), b(N, N), c(N, N)
integer i, j, k
double precision t1, t2
C
do i=1, N
do j=1, N
a(i, j)=i*j
b(i, j)=i*j
end do
end do
t1=omp_get_wtime()
C
!$omp parallel do shared(a, b, c) private(i, j, k)
do j=1, N
do i=1, N
c(i, j) = 0.0
do k=1, N
c(i, j)=c(i, j)+a(i, k)*b(k, j)
end do
end do
end do
t2=omp_get_wtime()
print *, "Time=", t2-t1
end

31b. .
2 31 [9]. Intel 11.0
, openmp.

1
2
4
8

165.442016
114.413227
68.271149
39.039399

164.433444
115.100835
67.953780
39.606582
2.
.

75


1. OpenMP Architecture Review Board (http://www.openmp.org/).
2. The Community of OpenMP Users, Researchers, Tool Developers and Providers (http://www.compunity.org/).
3. OpenMP Application Program Interface Version 3.0 May 2008
(http://www.openmp.org/mp-documents/spec30.pdf).
4. OpenMP? (http://parallel.ru/tech/tech_dev/openmp.html).
5. .., .. . .:
-, 2002. - 608 .
6. Barbara Chapman, Gabriele Jost, Ruud van der Pas. Using OpenMP: portable shared memory parallel programming (Scientific and Engineering
Computation). Cambridge, Massachusetts: The MIT Press., 2008. - 353 pp.
7. .. .
.-.: - , 2002. - 70 .
8. .. MPI: . -.: - , 2004. - 71 .
9.

(http://parallel.ru/cluster/).

76




OpenMP

18.03.2009. 6084/16.
1. . . . . 4,75.
.-. . 5,0. 100 . 1.
.
125009, , . . , 5/7.
.
119992, -2, , .