openmp
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| openmp [June 10, 2026 at 21:49] – Ivan Janevski | openmp [June 13, 2026 at 03:13] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| # OpenMP | # OpenMP | ||
| - | **OpenMP** is a parallel computing | + | **OpenMP** is a shared-memory parallelism |
| - | It' | + | The execution model is **fork-join**: |
| - | OpenMP is | ||
| - | |||
| - | ## Example | ||
| ```c | ```c | ||
| - | // #include < | ||
| #pragma omp parallel | #pragma omp parallel | ||
| { | { | ||
| int tid = omp_get_thread_num(); | int tid = omp_get_thread_num(); | ||
| - | printf(" | + | |
| + | | ||
| } | } | ||
| ``` | ``` | ||
| - | For example, if your environment variable is set to `export | + | |
| + | The thread count defaults | ||
| + | |||
| + | Adding more threads does not always mean proportionally faster code. [[amdahls-law|Amdahl' | ||
| + | |||
| + | ## Practice | ||
| + | |||
| + | Compile the hello-world above and run it: | ||
| + | |||
| + | ```bash | ||
| + | $ gcc -fopenmp -o hello hello.c | ||
| + | $ OMP_NUM_THREADS=4 ./hello | ||
| + | thread 2 of 4 | ||
| + | thread 0 of 4 | ||
| + | thread 3 of 4 | ||
| + | thread | ||
| ``` | ``` | ||
| - | Hello, I'm thread 4 | + | |
| - | Hello, I'm thread 1 | + | The output order is non-deterministic — run it a few times and you will get different permutations. Now try dropping `-fopenmp`: |
| - | Hello, I'm thread 3 | + | |
| - | Hello, I'm thread 2 | + | ```bash |
| - | Hello, I' | + | $ gcc -o hello hello.c |
| + | $ ./hello | ||
| + | thread 0 of 1 | ||
| ``` | ``` | ||
| + | |||
| + | Without the flag, every `#pragma omp` directive is silently ignored and the program runs as a single thread. This is the most useful OpenMP debugging technique: if your parallel output looks wrong, remove `-fopenmp` and check whether the serial output is correct first. | ||
| + | |||
| + | Here is a more realistic example: parallelising a sum of a billion integers with a single pragma. | ||
| + | |||
| + | ```c | ||
| + | // compile: gcc -O2 -fopenmp -o sum sum.c | ||
| + | // run: OMP_NUM_THREADS=4 ./sum | ||
| + | // description: | ||
| + | |||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | int main(void) { | ||
| + | long n = 1000000000L, | ||
| + | double t = omp_get_wtime(); | ||
| + | #pragma omp parallel for reduction(+: | ||
| + | for (long i = 0; i < n; i++) | ||
| + | sum += i; | ||
| + | printf(" | ||
| + | return 0; | ||
| + | } | ||
| + | ``` | ||
| + | |||
| + | On a 4-core machine this runs roughly 4× faster with `-fopenmp` than without. The only additions to the loop are the pragma line and the `reduction(+: | ||
| + | |||
| + | Try varying `OMP_NUM_THREADS` from 1 up to your core count and beyond. Speedup will plateau or even decline past the hardware thread count — that is thread management overhead and Amdahl' | ||
| + | |||
| + | ## Concepts | ||
| + | |||
| + | 1. [[data-sharing-openmp|Data sharing]] | ||
| + | 2. [[parallel-loops-openmp|Parallel loops]] | ||
| + | 3. [[collapse-openmp|Collapse]] | ||
| + | 4. [[reduction-openmp|Reduction]] | ||
| + | 5. [[scheduling-openmp|Scheduling]] | ||
| + | 6. [[simd-openmp|SIMD]] | ||
| + | 7. [[tasks-openmp|Tasks]] | ||
| + | 8. [[single-openmp|Single]] | ||
| + | 9. [[master-openmp|Master]] | ||
| + | 10. [[sections-openmp|Sections]] | ||
| + | 11. [[barrier-openmp|Barrier]] | ||
| + | 12. [[nowait-openmp|Nowait]] | ||
| + | 13. [[critical-sections-openmp|Critical sections]] | ||
| + | 14. [[atomic-openmp|Atomic]] | ||
| + | 15. [[flush-openmp|Flush]] | ||
| + | 16. [[false-sharing-openmp|False sharing]] | ||
| + | 17. [[thread-affinity-openmp|Thread affinity]] | ||
| + | 18. [[time-measurement-openmp|Time measurement]] | ||
| + | |||
| + | ## Overview | ||
| + | |||
| + | ### Directives | ||
| + | |||
| + | ```c | ||
| + | #pragma omp parallel | ||
| + | #pragma omp parallel for // distribute loop iterations across the team | ||
| + | #pragma omp parallel for reduction(+: | ||
| + | #pragma omp parallel sections | ||
| + | #pragma omp section | ||
| + | #pragma omp single | ||
| + | #pragma omp master | ||
| + | #pragma omp task // package work for any idle thread to execute | ||
| + | #pragma omp taskwait | ||
| + | #pragma omp barrier | ||
| + | #pragma omp critical | ||
| + | #pragma omp atomic | ||
| + | #pragma omp simd // assert the loop is safe to vectorise | ||
| + | #pragma omp flush // enforce memory visibility across threads | ||
| + | ``` | ||
| + | |||
| + | ### Functions | ||
| + | |||
| + | ```c | ||
| + | omp_get_thread_num() | ||
| + | omp_get_num_threads() | ||
| + | omp_get_max_threads() | ||
| + | omp_set_num_threads(n) | ||
| + | omp_get_num_procs() | ||
| + | omp_get_wtime() | ||
| + | omp_in_parallel() | ||
| + | ``` | ||
| + | |||
| + | ### Environment variables | ||
| + | |||
| + | ^ Variable ^ Default ^ Description ^ | ||
| + | | `OMP_NUM_THREADS` | core count | Number of threads to use in each parallel region | | ||
| + | | `OMP_SCHEDULE` | `static` | Default schedule kind and optional chunk size, e.g. `dynamic,4` | | ||
| + | | `OMP_PROC_BIND` | `false` | Thread-to-core affinity policy: `close`, `spread`, or `master` | | ||
| + | | `OMP_PLACES` | (unset) | Placement units for affinity: `cores`, `threads`, or `sockets` | | ||
| + | | `OMP_MAX_ACTIVE_LEVELS` | `1` | Maximum nesting depth of simultaneously active parallel regions | | ||
| + | | `OMP_DISPLAY_ENV` | `false` | Print OpenMP version and active settings at startup: `TRUE` or `VERBOSE` | | ||
openmp.1781128156.txt.gz · Last modified: by Ivan Janevski
