OpenMP. Diego Fabregat-Traver and Prof. Paolo Bientinesi WS16/17. HPAC, RWTH Aachen

Similar documents
OpenMP. Dr. William McDoniel and Prof. Paolo Bientinesi WS17/18. HPAC, RWTH Aachen

OpenMP - III. Diego Fabregat-Traver and Prof. Paolo Bientinesi WS15/16. HPAC, RWTH Aachen

OpenMP - II. Diego Fabregat-Traver and Prof. Paolo Bientinesi WS15/16. HPAC, RWTH Aachen

OpenMP I. Diego Fabregat-Traver and Prof. Paolo Bientinesi WS16/17. HPAC, RWTH Aachen

OpenMP 2. CSCI 4850/5850 High-Performance Computing Spring 2018

Lecture 4: OpenMP Open Multi-Processing

OpenMP. Application Program Interface. CINECA, 14 May 2012 OpenMP Marco Comparato

Parallel Programming

Introduction to OpenMP.

MPI and OpenMP (Lecture 25, cs262a) Ion Stoica, UC Berkeley November 19, 2016

Topics. Introduction. Shared Memory Parallelization. Example. Lecture 11. OpenMP Execution Model Fork-Join model 5/15/2012. Introduction OpenMP

Introduction to Standard OpenMP 3.1

Multi-core Architecture and Programming

OpenMP loops. Paolo Burgio.

Shared Memory Programming with OpenMP

Multithreading in C with OpenMP

Q6B8xqZ8n8bwjGdzBJ25X2utwnoEG

A Short Introduction to OpenMP. Mark Bull, EPCC, University of Edinburgh

OpenMP. OpenMP. Portable programming of shared memory systems. It is a quasi-standard. OpenMP-Forum API for Fortran and C/C++

ECE 574 Cluster Computing Lecture 10

OpenMP Overview. in 30 Minutes. Christian Terboven / Aachen, Germany Stand: Version 2.

Introduction to OpenMP. Lecture 4: Work sharing directives

High Performance Computing: Tools and Applications

OpenMP 4.5: Threading, vectorization & offloading

Introduction to OpenMP

CSL 860: Modern Parallel

Synchronization. Event Synchronization

Shared Memory Programming Paradigm!

HPC Practical Course Part 3.1 Open Multi-Processing (OpenMP)

Introduction to OpenMP

by system default usually a thread per CPU or core using the environment variable OMP_NUM_THREADS from within the program by using function call

OpenMP. António Abreu. Instituto Politécnico de Setúbal. 1 de Março de 2013

Introduction to OpenMP

OpenMP Introduction. CS 590: High Performance Computing. OpenMP. A standard for shared-memory parallel programming. MP = multiprocessing

Computational Mathematics

Allows program to be incrementally parallelized

OpenMP dynamic loops. Paolo Burgio.

Shared Memory Parallelism - OpenMP

OpenMP C and C++ Application Program Interface Version 1.0 October Document Number

Module 10: Open Multi-Processing Lecture 19: What is Parallelization? The Lecture Contains: What is Parallelization? Perfectly Load-Balanced Program

Parallel Programming in C with MPI and OpenMP

Session 4: Parallel Programming with OpenMP

EE/CSCI 451: Parallel and Distributed Computation

[Potentially] Your first parallel application

OpenMP examples. Sergeev Efim. Singularis Lab, Ltd. Senior software engineer

COSC 6374 Parallel Computation. Introduction to OpenMP. Some slides based on material by Barbara Chapman (UH) and Tim Mattson (Intel)

Mango DSP Top manufacturer of multiprocessing video & imaging solutions.

OpenMP Programming. Prof. Thomas Sterling. High Performance Computing: Concepts, Methods & Means

UvA-SARA High Performance Computing Course June Clemens Grelck, University of Amsterdam. Parallel Programming with Compiler Directives: OpenMP

Parallel Programming in C with MPI and OpenMP

Parallel Programming with OpenMP. CS240A, T. Yang

Parallel programming using OpenMP

Parallel Programming in C with MPI and OpenMP

OpenMP Algoritmi e Calcolo Parallelo. Daniele Loiacono

OpenMP Language Features

Introduction to OpenMP

15-418, Spring 2008 OpenMP: A Short Introduction

Introduction to OpenMP. OpenMP basics OpenMP directives, clauses, and library routines

COSC 6374 Parallel Computation. Introduction to OpenMP(I) Some slides based on material by Barbara Chapman (UH) and Tim Mattson (Intel)

CS 470 Spring Mike Lam, Professor. Advanced OpenMP

Introduction to OpenMP. Motivation

Programming with OpenMP*

Introduction to OpenMP

OpenMP Tutorial. Dirk Schmidl. IT Center, RWTH Aachen University. Member of the HPC Group Christian Terboven

CS4961 Parallel Programming. Lecture 5: More OpenMP, Introduction to Data Parallel Algorithms 9/5/12. Administrative. Mary Hall September 4, 2012

Open Multi-Processing: Basic Course

EPL372 Lab Exercise 5: Introduction to OpenMP

Distributed Systems + Middleware Concurrent Programming with OpenMP

Overview: The OpenMP Programming Model

Introduction to OpenMP

CS4961 Parallel Programming. Lecture 9: Task Parallelism in OpenMP 9/22/09. Administrative. Mary Hall September 22, 2009.

OpenMP 4. CSCI 4850/5850 High-Performance Computing Spring 2018

Introduction to. Slides prepared by : Farzana Rahman 1

OpenMP. Dr. William McDoniel and Prof. Paolo Bientinesi WS17/18. HPAC, RWTH Aachen

Parallel Programming using OpenMP

Parallel Programming using OpenMP

Shared Memory Programming Model

High Performance Computing: Tools and Applications

OpenMP 4.0/4.5: New Features and Protocols. Jemmy Hu

CS 470 Spring Mike Lam, Professor. OpenMP

CMSC 714 Lecture 4 OpenMP and UPC. Chau-Wen Tseng (from A. Sussman)

Cluster Computing 2008

Parallel Processing Top manufacturer of multiprocessing video & imaging solutions.

!OMP #pragma opm _OPENMP

Loop Modifications to Enhance Data-Parallel Performance

Programming with Shared Memory PART II. HPC Fall 2012 Prof. Robert van Engelen


Parallel Computing Parallel Programming Languages Hwansoo Han

Programming with Shared Memory PART II. HPC Fall 2007 Prof. Robert van Engelen

NUMERICAL PARALLEL COMPUTING

CS 470 Spring Mike Lam, Professor. OpenMP

Data Environment: Default storage attributes

A common scenario... Most of us have probably been here. Where did my performance go? It disappeared into overheads...

OpenMP: Open Multiprocessing

UPDATES. 1. Threads.v. hyperthreading

OpenMP - Introduction

OpenMP: Open Multiprocessing

OPENMP OPEN MULTI-PROCESSING

OpenMP Tutorial. Seung-Jai Min. School of Electrical and Computer Engineering Purdue University, West Lafayette, IN

Shared Memory Parallelism using OpenMP

Transcription:

OpenMP Diego Fabregat-Traver and Prof. Paolo Bientinesi HPAC, RWTH Aachen fabregat@aices.rwth-aachen.de WS16/17

Worksharing constructs To date: #pragma omp parallel created a team of threads We distributed the work manually id, nths,... OpenMP also provides directives for automatic distribution of work: Loop construct Sections construct Single construct Diego Fabregat OpenMP 2 / 44

Loop construct Syntax: Example: #pragma omp for [clause [, clause]...] for-loop #pragma omp parallel { #pragma omp for for (i = 0; i < n; i++) [...] The iterations of the associated loop are executed in parallel by the team of threads that encounter it See, for instance, 11.loop-worksharing.c Diego Fabregat OpenMP 3 / 44

Loop construct - Canonical form Restrictions in the form of the loop to simplify the compiler optimizations Only for loops Number of iterations can be counted: integer counter which is incremented (decremented) until some specified upper (lower) bound is reached Remember: one entry point, one exit point No break statement continue and exit allowed. Diego Fabregat OpenMP 4 / 44

Loop construct - Canonical form Loops must have the canonical form for (init-expr ; var relop b ; incr-expr) where: init-expr: initializes the loop counter var via an integer expression relop is one of: <, <=, >, >= b is also an integer expression incr-expr: increments or decrements var by an integer amount: ++var, var++, --var, var-- var += incr, var -= incr var = var + incr, var = var - incr Example (see also 11.canonical-loop.c): for (i = 0; i < n; i += 4) Diego Fabregat OpenMP 5 / 44

Combined parallel for Sequential: int i; for (i = 0; i < N; i++) z[i] = alpha * x[i] + y[i]; Parallel region: #pragma omp parallel { int i, id, nths, istart, iend; id = omp_get_thread_num(); nths = omp_get_num_threads(); istart = id * N / nths; iend = (id+1) * N / nths; if (id == nths-1) iend = N; for (i = istart; i < iend; i++) z[i] = alpha * x[i] + y[i]; Diego Fabregat OpenMP 6 / 44

Combined parallel for Sequential: int i; for (i = 0; i < N; i++) z[i] = alpha * x[i] + y[i]; Parallel region: #pragma omp parallel { int i, id, nths, istart, iend; id = omp_get_thread_num(); nths = omp_get_num_threads(); istart = id * N / nths; iend = (id+1) * N / nths; if (id == nths-1) iend = N; for (i = istart; i < iend; i++) z[i] = alpha * x[i] + y[i]; Loop construct: #pragma omp parallel { int i; #pragma omp for for (i = 0; i < N; i++) z[i] = alpha * x[i] + y[i]; Diego Fabregat OpenMP 6 / 44

Combined parallel for Sequential: int i; for (i = 0; i < N; i++) z[i] = alpha * x[i] + y[i]; Parallel region: #pragma omp parallel { int i, id, nths, istart, iend; id = omp_get_thread_num(); nths = omp_get_num_threads(); istart = id * N / nths; iend = (id+1) * N / nths; if (id == nths-1) iend = N; for (i = istart; i < iend; i++) z[i] = alpha * x[i] + y[i]; Loop construct: #pragma omp parallel { int i; #pragma omp for for (i = 0; i < N; i++) z[i] = alpha * x[i] + y[i]; Shortcut: int i; #pragma omp parallel for for (i = 0; i < N; i++) z[i] = alpha * x[i] + y[i]; Diego Fabregat OpenMP 6 / 44

Loop construct Guidelines: Identify the compute intensive loops Can the iterations be run independently? If needed/possible remove dependencies Add the for directive Consider alternative schedulings if bad load balancing Diego Fabregat OpenMP 7 / 44

Loop construct - Dependencies So far, trivially parallelizable loops: for (i = 0; i < n; i++) { z[i] = alpha * x[i] + y[i]; w[i] = z[i] * z[i] What if we run the following code in parallel? fib[0] = fib[1] = 1; for (i = 2; i < n; i++) fib[i] = fib[i-1] + fib[i-2] Possible outputs with n = 10 and 2 threads: a) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55] b) [1, 1, 2, 3, 5, 0, 0, 0, 0, 0] Think about it: Why? Diego Fabregat OpenMP 8 / 44

Loop construct - Dependencies Loop-carried dependencies A memory location is written in one iteration, and it is also read or written in another iteration for (i = 1; i < n; i++) a[i] = a[i] + a[i-1] Race condition: results depends on the order in which operations are performed Classification of dependencies: Flow/True dependencies Anti dependencies Output dependencies Diego Fabregat OpenMP 9 / 44

Loop construct - Dependencies Flow dependence: Iteration i writes to a location Iteration i + 1 reads from the location We can remove some loop-carried dependencies. For instance: Reductions: x = x + a[i]; Induction variables: j = 5; for (i = 1; i < n; i++) { j += 2; a[i] = f(j); Rewrite j += 2; as j = 5 + 2*i; Diego Fabregat OpenMP 10 / 44

Loop construct - Dependencies Anti dependence: Iteration i reads to a location Iteration i + 1 writes from the location Example for (i = 0; i < n-1; i++) a[i] = a[i+1] + f(i); Split the loop, and make a copy of array a #pragma omp parallel for for (i = 0; i < n-1; i++) a2[i] = a[i+1]; #pragma omp parallel for for (i = 0; i < n-1; i++) a[i] = a2[i] + f(i); Diego Fabregat OpenMP 11 / 44

Loop construct - Dependencies Output dependence: Iteration i writes to a location Iteration i + 1 writes from the location Example for (i = 0; i < n; i++) { tmp = A[i]; A[i] = B[i]; B[i] = tmp; Scalar expansion of tmp to array unnecessarily expensive. Make tmp private. #pragma omp parallel for private(tmp) for (i = 0; i < n; i++) { tmp = A[i]; A[i] = B[i]; B[i] = tmp; Diego Fabregat OpenMP 12 / 44

Loop construct - Dependencies Other situations Even/odd parallelization for (i = 2; i < n; i++) a[i] = a[i-2] + x; can be rewritten as for (i = 2; i < n; i+=2) a[i] = a[i-2] + x; for (i = 3; i < n; i+=2) a[i] = a[i-2] + x; Even though both loops still present a loop-carried dependence, they are independent from one another and we can, for instance, use task parallelism to run them as two independent tasks. Not a dependence: for (i = 0; i < n; i++) a[i] = a[i+n] + x; Diego Fabregat OpenMP 13 / 44

Exercise - Loop-carried dependencies Try to parallelize the different pieces of code below. for ( i = 0; i < n-1; i++ ) a[i] = a[i+1] + b[i] * c[i]; for ( i = 1; i < n; i++ ) a[i] = a[i-1] + b[i] * c[i]; t = 1; for ( i = 0; i < n-1; i++ ) { a[i] = a[i+1] + b[i] * c[i]; t = t * a[i]; Diego Fabregat OpenMP 14 / 44

Loop construct - Clauses #pragma omp for [clause [, clause]...] The following clauses apply: private, firstprivate, lastprivate reduction schedule collapse nowait Diego Fabregat OpenMP 15 / 44

Loop construct - Clauses Data-sharing attributes private and firstprivate as in the parallel construct Important: the iterator variable is made private by default. That is, in for (i = 0; i < n; i += 4) i is made private automatically lastprivate (list): the last value of a private variable listed in this clause is available after the construct completes By last iteration we mean the value from the iteration that would come last in a sequential execution See 11.loop-lastprivate.c Diego Fabregat OpenMP 16 / 44

Loop construct - Clauses reduction (see 11.loop-reduction.c) double sum = alpha; #pragma omp parallel for reduction(+:sum) for ( int i = 0; i < N; i++ ) { sum += x[i] * y[i] // Accumulate to sum (no race condition) double sum = alpha; // We can have any initial value here // This is application specific #pragma omp parallel { double priv_sum = 0.0; // Initializer (0.0 for sum of doubles) #pragma omp for // Same computation on the local accumulator for ( int i = 0; i < N; i++ ) { priv_sum += x[i] * y[i] // Accumulate to your private copy of sum #pragma omp critical // Reduce partial sums using the sum += priv_sum; // Combiner function (+ in this case) Diego Fabregat OpenMP 17 / 44

Loop construct - Scheduling Scheduling: how loop iterations are distributed among threads. To achieve best performance, threads must be busy most of the time, minimizing the time they remain idle, wasting resources. Keys: Good load balance (work evenly distributed) Minimum scheduling overhead Minimum synchronization Diego Fabregat OpenMP 18 / 44

Loop construct - Scheduling OpenMP allows us to choose among several scheduling schemes via the schedule clause schedule(kind[, chunk_size]) where kind is one of static dynamic guided auto runtime The value of chunk_size influences the divisions into chunks of the iteration space and the kind specifies how the chunks are distributed among threads. Diego Fabregat OpenMP 19 / 44

Loop construct schedule: static Divide the iterations in NUM_THREADS (roughly) equal chunks and give one to each of them (in order) If chunk_size is specified, divide in chunks of size chunk_size, and distribute them cyclically in a round robin fashion Example: #pragma omp for schedule(static, 4) for (i = 0; i < 20; i++) [...] Assuming execution with 2 threads: TH0: [0-3] TH1: [4-7] TH0: [8-11] TH1: [12-15] TH0: [16-19] Diego Fabregat OpenMP 20 / 44

Loop construct - Clauses schedule: dynamic Conceptually, this scheme creates a queue of chunks, from which the threads keep grabing chunks to execute, until no more chunks are left By default, chunk_size equals 1 Example: #pragma omp for schedule(dynamic, 2) for (i = 0; i < 10; i++) [...] Possible run assuming execution with 2 threads: TH0: [0-1] TH1: [2-3] TH1: [4-5] TH0: [6-7] TH1: [8-9] Diego Fabregat OpenMP 21 / 44

Loop construct schedule: guided Similar to dynamic Difference: start with large chunk sizes, which exponentially decrease in size Chunks consist of at least chunk_size iterations (except maybe the last one) chunk_size defaults to 1 Example: #pragma omp for schedule(guided, 2) for (i = 0; i < 40; i++) [...] Possible run assuming execution with 3 threads: TH2: [0-13] TH0: [14-22] T1: [23-28] [29-32]... Diego Fabregat OpenMP 22 / 44

Loop construct schedule: auto and runtime auto Decision on scheduling delegated to the compiler/runtime The programmer gives freedom to the implementation May simply resort to static or dynamic runtime Decision on scheduling is deferred until run time Schedule and chunk size are taken from internal variables May be specified via a routine call or via environment variables: omp_set_schedule( kind, chunk_size ) export OMP_SCHEDULE="kind,chunk_size" Mainly used for testing (so that we do not need to edit and recompile every time) Diego Fabregat OpenMP 23 / 44

Loop construct - Scheduling Most used: static and dynamic static: Workload is predetermined and predictable by the programmer Cyclic distribution allows good load balancing Scheduling is done at compile time, adding little parallel overhead dynamic: Unpredictable/variable work per iteration Decisions on scheduling made at runtime, adding overhead See: 11.loop-schedule.c Diego Fabregat OpenMP 24 / 44

Loop construct - Clauses collapse Syntax: collapse(n) Indicates how many loops are associated with the loop construct n must be a constant positive integer expression The iterations of the n loops are collapsed into one larger iteration space The order of the collapsed space is that of the equivalent sequential execution of the iterations Diego Fabregat OpenMP 25 / 44

Loop construct - Clauses collapse Example: #pragma omp for collapse(3) for (i = 0; i < m; i++) for (j = 0; j < n; j++) for (k = 0; k < l; k++) [...] The resulting iteration space is of size m n l Diego Fabregat OpenMP 26 / 44

Loop construct - Clauses nowait Syntax: #pragma omp for nowait Removes the implicit barrier at the end of the construct When threads reach the end of the construct, they will proceed immediately to perform other work Allows fine tuning of a program s performance Use with care, incorrect usage will introduce bugs Diego Fabregat OpenMP 27 / 44

Loop construct - Clauses nowait Example #pragma omp parallel { #pragma omp for nowait for (i = 0; i < n; i++) a[i] = a[i] + i; #pragma omp for for (i = 0; i < m; i++) b[i] = 2 * b[i]; Diego Fabregat OpenMP 28 / 44

Loop construct - Clauses nowait The following example shows an incorrect usage of nowait #pragma omp parallel { #pragma omp for nowait for (i = 0; i < n; i++) a[i] = a[i] + i; #pragma omp for for (i = 0; i < n; i++) b[i] = 2 * a[i]; The code assumes that the distribution of iterations to threads is identical for both loops Thus, removing the barrier may lead to wrong results Diego Fabregat OpenMP 29 / 44

Loop construct - Clauses nowait Exception: Loops belong to the same parallel region Both loops use static scheduling Both loops run for the same number of iterations Both specify the same chunk_size or do not specify it at all (none is associated with the SIMD construct) If all of the above holds, then, and only then, can we assume that the same iteration numbers are assigned to the same threads in both loops. Diego Fabregat OpenMP 30 / 44

Loop construct - Clauses nowait // CORRECT :) #pragma omp parallel { #pragma omp for nowait schedule(static) for (i = 0; i < n; i++) a[i] = a[i] + i; #pragma omp for schedule(static) for (i = 0; i < n; i++) b[i] = 2 * a[i]; Diego Fabregat OpenMP 31 / 44

Sections Diego Fabregat OpenMP 32 / 44

Sections The sections construct allows different threads to carry out different tasks (task parallelism) Non-iterative worksharing construct It consists of a pair of directives: sections and section sections indicates the start of the construct (enclosing the region with the multiple tasks) section marks each different section/task (a structured block) Diego Fabregat OpenMP 33 / 44

Sections #pragma omp parallel { #pragma omp sections { #pragma omp section computation_x() #pragma omp section computation_y() #pragma omp section computation_z() Think of a queue of executable blocks of code (each individual section) Theads grab one block at a time from the queue and execute it, until no more blocks remain Each block is executed only once See 12.sections.c Diego Fabregat OpenMP 34 / 44

Exercise Consider the following sequence of operations. Assuming the only dependencies among the operations are given by their input and output variables, write a piece of OpenMP code that exposes as much parallelism as possible using the sections and section constructs. mx = mean( x ); my = mean( y ); fout = f( mx, my ); gout = g( mx, my ); final = summary( fout, gout ); Hints: #pragma omp parallel #pragma omp sections #pragma omp section Hint: You may need multiple sections regions. Diego Fabregat OpenMP 35 / 44

Sections - Clauses #pragma omp sections [clause [, clause]...] The following clauses apply: private, firstprivate, lastprivate reduction nowait Worksharing construct! Implicit barrier at the end of sections! Diego Fabregat OpenMP 36 / 44

Master and Single Diego Fabregat OpenMP 37 / 44

Master and Single The master and single constructs guarantee that code in a parallel region is executed by one single thread Initialization of data, I/O,... Both constructs apply to a structured block Differences: The master construct guarantees the block is executed only by the master thread The single construct guarantees the block is executed by any one and only one thread A single construct has an implicit barrier at the end A master construct does not Efficiency may differ. Application and implementation dependent. Diego Fabregat OpenMP 38 / 44

Master 06.master.c #pragma omp parallel num_threads(2) { int id = omp_get_thread_num(); #pragma omp master { printf("[%d] Executed only by the master thread\n", id); printf("[%d] Executed by all threads\n", id); Diego Fabregat OpenMP 39 / 44

Single 06.single.c #pragma omp parallel num_threads(2) { int id = omp_get_thread_num(); #pragma omp single { printf("[%d] Executed by only one thread\n", id); printf("[%d] Executed by all threads\n", id); Diego Fabregat OpenMP 40 / 44

Single - Clauses #pragma omp single [clause [, clause]...] The following clauses apply: private, firstprivate nowait single is a worksharing construct! Remember: Implicit barrier at the end of single! master is not a worksharing construct! Remember: NO implicit barrier at the end of master! Diego Fabregat OpenMP 41 / 44

Exercise Parallelize the body of the while loop in the following code. Use the for construct to parallelize the for loop. Use the master/single construct to serialize the portions of the code that should be executed by only one thread. Produce two versions of your code. #include <stdio.h> #include <stdlib.h> #define N 1000 int main( void ) { int iter = 0; float buffer_in[n*n], buffer_out[n*n]; while (1) { iter++; printf( "Timestep %d\n", iter ); read_input( buffer_in ); for (i = 0; i < N; i++) Hints: #pragma omp parallel #pragma omp master #pragma omp single Challenge: Pay special attention to the process_signal( &buffer_in[i*n], &buffer_out[i*n] ); write_output( buffer_out ); subtle differences between master and single Diego Fabregat OpenMP 42 / 44

Pitfalls - Deadlocks From the OpenMP 4.0 specifications (Section 2.7): Each worksharing region must be encountered by all threads in a team or by none at all, unless cancellation has been requested for the innermost enclosing parallel region. The sequence of worksharing regions and barrier regions encountered must be the same for every thread in a team. Otherwise, the behavior is unspecified, leading to deadlocks or unexpected behavior. See 14.worksharing-order.c Diego Fabregat OpenMP 43 / 44

Summary Work-sharing #pragma omp parallel Indicates a portion of code to be parallelized Creates team of threads Replicates work: distribute manually or via worksharing constructs Clauses to control data-sharing attributes, number of threads, etc. #pragma omp for Work-sharing construct Distributes iterations among threads Clauses to control data-sharing attributes, load balancing, etc. Careful with loop-carried dependencies! Also pragma omp sections/section pragma omp single pragma omp master (not a work-sharing construct) Diego Fabregat OpenMP 44 / 44