Překlad a spouštění OpenMP úloh
-------------------------------
Překlad a spouštění `OpenMP `_ (vláknově paralelizovaných) programů poskytují na našich strojích s Ubuntu 22.04 (`přehled strojů v klastru `_) následující překladače Fortranu a C/C++:
* `GNU překladače `_ ``gfortran``, ``gcc``, ``g++`` verze 11, použít lze i verze 9: ``gfortran-9`` ad. a 12: ``gfortran-12`` ad.,
* (po ``source load_intel``) překladače `Intel oneAPI HPC Toolkitu `_ 2022.x, jednak Classic ``ifort``, ``icc``, ``icpc``, jednak novější na bázi `LLVM `_ ``ifx``, ``icx``, ``icpx``,
* (po ``source load_nv``) `Nvidia překladače `_ verze 22.x ``nvfortran``, ``nvc``, ``nvc++`` (na bázi `LLVM `_),
* (po ``source load_amd``) `AMD překladače `_ verze 3.x ``flang``, ``clang``, ``clang++`` (na bázi `LLVM `_).
Překladače podporují `specifikace OpenMP `_ 4.5 až 5.x.
Překladače na bázi `LLVM `_ (Intel, Nvidia, AMD) mohou poskytnout jiný (lepší i horší) výkon aplikací než klasické překladače (GNU a Intel Classic), včetně účinnosti OpenMP a optimalizace; s výjimkou Intelu nejsou LLVM fortranské překladače dosud k dispozici pro Windows.
GNU a Nvidia překladače nabízejí OpenMP (a také `OpenACC `_) podporu grafických karet Nvidia (GPU), Intel LLVM překladače mají OpenMP pro grafické karty Intel, AMD překladače deklarují podporu AMD GPUs.
Vláknová paralelizace je zabudována v řadě instalovaných knihoven (Intel MKL, BLAS, LAPACK, FFTW ad.); je vhodné uvážit, zda využít OpenMP paralelizaci vlastními direktivami, paralelizaci zabudovanou v knihovnách nebo obojí.
Při překladu programů je třeba přidat volbu pro aktivaci OpenMP, obvykle také pro optimalizaci a případně pro diagnostiku. Před spuštěním programu se nastavuje počet vláken a bývá vhodné zajistit se proti přetečení zásobníku. Pro překlad i spouštění s jinými než GNU překladači je na našem klastru nezbytné použít příkazy pro upřednostnění cest k potřebným knihovnám příslušných překladačů: ``source load_intel``, ``source load_nv`` nebo ``source load_amd``.
OpenMP s GNU překladači
^^^^^^^^^^^^^^^^^^^^^^^
Default `GNU Compiler Collection `_ (GCC) v Ubuntu 22.04 je ve `verzi 11.2.0 `_. Těmito překladači jsou zpracovány i knihovny v repozitářích Ubuntu, tyto knihovny je tedy vhodné používat právě s default GNU překladači::
# GNU Fortran compilation with OpenMP (Linux, Windows)
gfortran -fopenmp -Ofast file.f90 # with optimization
gfortran -fopenmp -fopt-info-all-omp file.f90 # with diagnostics
gfortran file.f90 -llapack # with a parallelized library
Instalovány jsou i starší a novější verze GNU překladačů (`v9.4.0 `_ a `v12.0.1 `_). Jejich OpenMP může a nemusí být kompatibilní s vláknově paralelizovanými knihovnami z repozitářů Ubuntu, smysluplné je jejich použití spíše pro soběstačné programy bez vnějších knihoven. Verze 9 může pomoci s překladem starších programů s vlastnostmi mimo současný standard, verze 12 může naopak podpořit novinky. ::
# Compilation with other versions of GNU Fortran
gfortran-9 -fopenmp -Ofast file.f90
gfortran-12 -fopenmp -Ofast file.f90
GNU překladače jsou k dispozici i `pro Windows `_.
Před spuštěním vláknově paralelizovaného programu je dobré vědět, kolik má daný stroj hardwarových jader (naše `tabulka `_), uvážit využití `hyper-threadingu `_ (osazení jednoho jádra dvěma vlákny) a ověřit si, kolik jader je vytíženo jinými úlohami (lokálně programy ``uptime`` a ``top``, pro celý klastr skript ``guptime`` nebo link `guptime NOW `_). Počet požadovaných vláken je pak vhodné nastavit explicitně pomocí proměnné prostředí ``OMP_NUM_THREADS``, neboť defaulty překladačů jsou různé a především, na našem klastru je tato proměnná předdefinována hodnotou ``1``. ::
# Setting the thread count
export OMP_NUM_THREADS=8 # Linux
set OMP_NUM_THREADS=8 # Windows
# Running a multi-threaded process
./a.out # Linux
OMP_NUM_THREADS=8 ./a.out # one-line alternative
a # Windows
Pokud paralelizovaný program po spuštění padá (*Segmentation fault*, *Stack overflow* apod.), ačkoliv jako neparalelizovaný běží, může být příčinou odlišné zacházení paralelizovaného programu se zásobníkem. V Linuxu může pomoci uvolnění default limitu na velikost zásobníku příkazem shellu ``ulimit``, někdy také zvýšení velikosti zásobníku pomocí proměnné prostředí ``OMP_STACKSIZE``::
# Preventing stack overflow
ulimit -s unlimited # removing a bash limit on stacksize
ulimit -a # check all actual limits
export OMP_STACKSIZE=256M # increasing OpenMP stacksize (in MB); necessary to guess
GNU překladače v Linuxu nabízejí využití OpenMP pro Nvidia (a také AMD) grafické karty (`GNU Offloading and Multi-Processing Project `_, `Offloading Support in GCC `_). K tomu účelu je na našem klastru instalován balíček ``gcc-11-offload-nvptx``, podporující kromě OpenMP i překlad alternativním systémem `OpenACC `_. Překladové řádky::
# GNU Fortran with OpenMP and OpenACC for Nvidia GPU (Linux only)
gfortran -fopenmp -foffload=nvptx-none -fopt-info-all-omp file.f90 # OpenMP
gfortran -fopenacc -foffload=nvptx-none -fopt-info-all-omp file.f90 # OpenACC
Užitek mohou přinést volby ``-foffload=``, ``-foffload-options=`` a proměnné prostředí ``GOMP_DEBUG``, ``GCC_ACC_NOTIFY`` či ``OMP_TARGET_OFFLOAD``.
Následující ukázky mají dobrý výkon s OpenACC direktivami a nevalný s OpenMP direktivami. Podstatně lepší GPU výkon s OpenMP direktivami poskytují Nvidia překladače.
*Link s ukázkovými programy* bude doplněn.
OpenMP s Intel překladači
^^^^^^^^^^^^^^^^^^^^^^^^^
Na klastru jsou instalovány `Intel oneAPI Base a HPC Toolkits `_ 2022.x, přinášející jednak stagnující *Classic* překladače ``ifort``, ``icc``, ``icpc`` (podpora OpenMP pro CPU, nikoliv pro GPU, podpora `Coarray Fortranu `_), jednak překladače rozvíjené na bázi LLVM ``ifx``, ``icx``, ``icpx`` (podpora OpenMP pro CPU a Intel GPU, bez podpory Coarray Fortranu), viz `Release Notes `_. Součástí je i kvalitní (optimalizovaná a paralelizovaná) knihovna `Intel Math Kernel Library `_ (MKL) s lineární algebrou (přímé řešiče pro plné i řídké matice, iterativní řešiče), Fourierovou transformací ad. Vše je k dispozici i pro Windows. MKL knihovnu lze připojovat také ke GNU a Nvidia překladačům, v Linuxu i ve Windows (`MKL Link Line Advisor `_, náš link `Připojování knihoven `_). Nejistý je výkon MKL knihovny na AMD procesorech (*geofy5-6*), na nich je vhodné porovnávat s výkonem ekvivalentních knihoven AMD překladačů. Intel Classic a LLVM překladače sdílejí mnoho voleb, je tam i řada odchylek. Volby překladačů v Linuxu a Windows mohou mít odchylnou syntaxi. ::
# Intel Fortran Classic compilation with OpenMP (Linux, Windows)
source load_intel # activation of Intel oneAPI compilers
ifort -qopenmp -Ofast file.f90 # with optimization (Linux)
ifort -Qopenmp -Ofast file.f90 # with optimization (Windows)
ifort -qopenmp -diag-enable=openmp file.f90 # with diagnostics (Linux)
ifort -Qopenmp -Qdiag-enable:openmp file.f90 # with diagnostics (Windows)
ifort file.f90 -qmkl # with the MKL library (Linux)
ifort file.f90 -Qmkl # with the MKL library (Windows)
# Intel Fortran LLVM compilation with OpenMP (Linux, Windows)
ifx ... # same options as shown for ifort
Před spuštěním vláknově paralelizovaného programu je dobré vědět, kolik má daný stroj hardwarových jader (naše `tabulka `_), uvážit využití `hyper-threadingu `_ (osazení jednoho jádra dvěma vlákny) a ověřit si, kolik jader je vytíženo jinými úlohami (lokálně programy ``uptime`` a ``top``, pro celý klastr skript ``guptime`` nebo link `guptime NOW `_). Počet požadovaných vláken je pak vhodné nastavit explicitně pomocí proměnné prostředí ``OMP_NUM_THREADS`` a pro knihovnu MKL pomocí proměnné ``MKL_NUM_THREADS``, neboť na našem klastru jsou obě proměnné předdefinovány hodnotou ``1``. ::
# Setting the thread count
export OMP_NUM_THREADS=8 # OpenMP general setting (Linux)
export MKL_NUM_THREADS=8 # Intel MKL specific setting (Linux)
set OMP_NUM_THREADS=8 # Windows
set MKL_NUM_THREADS=8 # Windows
# Running a multi-threaded process
./a.out # Linux
OMP_NUM_THREADS=8 ./a.out # one-line alternative
file # Windows: executable files retain the first source name
Pokud paralelizovaný program po spuštění padá (*Segmentation fault*, *Stack overflow* apod.), ačkoliv jako neparalelizovaný běží, může být příčinou odlišné zacházení paralelizovaného programu se zásobníkem. Pomoci může překlad s preferencí ukládání polí jinam než na zásobník (``-heap-arrays``), v Linuxu také uvolnění default limitu na velikost zásobníku příkazem shellu ``ulimit``, někdy také zvýšení velikosti zásobníku pomocí proměnné prostředí ``OMP_STACKSIZE``::
# Preventing stack overflow
ifort -qopenmp -heap-arrays file.f90 # arrays on the heap instead of the stack
ulimit -s unlimited # removing bash limit on stacksize
ulimit -a # check all actual limits
export OMP_STACKSIZE=256M # increasing OpenMP stacksize (in MB); necessary to guess
Intel překladače nabízejí využití OpenMP pro Intel grafické karty. Dosud nevyzkoušeno, ostatně nejméně deset našich Nvidia GPU je podstatně výkonnějších než soudobé Intel GPU.
OpenMP s Nvidia překladači
^^^^^^^^^^^^^^^^^^^^^^^^^^
Na klastru je instalován balík `Nvidia HPC SDK `_ verze 22.x, přinášející překladače ``nvfortran``, ``nvc`` a ``nvc++`` s podporou jak OpenMP pro CPU a Nvidia GPU, tak i alternativního systému `OpenACC `_ (viz `Nvidia OpenACC Getting Started Guide `_). Součástí je také několik paralelizovaných knihoven s lineární algebrou ad. Balík je dodáván pro Linux, dosud nikoliv pro Windows. ::
# Nvidia Fortran compilation with OpenMP (Linux only)
source load_nv # activation of Nvidia HPC SDK
nvfortran -mp -fast file.f90 # with optimization
nvfortran -mp -Minfo=mp file.f90 # with diagnostics
nvfortran file.f90 -llapack # with a parallelized library
Před spuštěním vláknově paralelizovaného programu je dobré vědět, kolik má daný stroj hardwarových jader (naše `tabulka `_), uvážit využití `hyper-threadingu `_ (osazení jednoho jádra dvěma vlákny) a ověřit si, kolik jader je vytíženo jinými úlohami (lokálně programy ``uptime`` a ``top``, pro celý klastr skript ``guptime`` nebo link `guptime NOW `_). Počet požadovaných vláken je pak vhodné nastavit explicitně pomocí proměnné prostředí ``OMP_NUM_THREADS``, neboť na našem klastru je tato proměnná předdefinována hodnotou ``1``. ::
# Setting the thread count
export OMP_NUM_THREADS=8
# Running a multi-threaded process
./a.out
OMP_NUM_THREADS=8 ./a.out # one-line alternative
Pokud paralelizovaný program po spuštění padá (*Segmentation fault*, *Stack overflow* apod.), ačkoliv jako neparalelizovaný běží, může být příčinou odlišné zacházení paralelizovaného programu se zásobníkem. Pomoci může uvolnění default limitu na velikost zásobníku příkazem shellu ``ulimit``, někdy také zvýšení velikosti zásobníku pomocí proměnné prostředí ``OMP_STACKSIZE``::
# Preventing stack overflow
ulimit -s unlimited # removing bash limit on stacksize
ulimit -a # check all actual limits
export OMP_STACKSIZE=256M # increasing OpenMP stacksize (in MB); necessary to guess
Silnou stránkou Nvidia (dříve PGI) překladačů je dlouholetá podpora programování Nvidia GPU. Překladače nabízejí několik přístupů, mezi nimi také OpenMP a alternativní OpenACC, včetně obvykle úspěšného chodu programů paralelizovaných pro GPU paralelizovaně na CPU (*CPU fallback*). Překladové řádky::
# Nvidia Fortran with OpenMP and OpenACC for Nvidia GPU (Linux only)
nvfortran -mp=gpu -Minfo=mp file.f90 # OpenMP for GPU
nvfortran -mp=multicore -Minfo=mp file.f90 # OpenMP with parallelized CPU fallback
nvfortran -acc -Minfo=accel file.f90 # OpenACC for GPU
nvfortran -acc=multicore -Minfo=accel file.f90 # OpenACC with parallelized CPU fallback
nvfortran -acc=host -Minfo=accel file.f90 # OpenACC with sequential CPU fallback
Užitek mohou přinést proměnné prostředí pro debugging ``NV_OMP_NOTIFY`` a ``NV_ACC_NOTIFY``, profiling ``NV_ACC_TIME`` a CPU fallback ``OMP_TARGET_OFFLOAD``.
Nvidia překladače až příliš rychle omezují dolní limit na *compute capability* (*cc*) použitelných grafických karet (v22.x: pro OpenACC je minimální *cc* 3.5, pro OpenMP 7.0; *cc* našich strojů viz `tabulka `_); soudobé GNU překladače podporují i starší GPU.
Následující ukázky mají výborný výkon s OpenACC i OpenMP: *link s ukázkovými programy* bude doplněn.
Poznámky
^^^^^^^^
Na strojích máme předdefinovány proměnné prostředí ``OMP_NUM_THREADS`` a ``MKL_NUM_THREADS`` hodnotami 1 (běh úlohy na 1 vláknu, bez paralelizace). Je lépe si tyto hodnoty vědomě upravit podle potřeb aplikace a aktuálního zatížení stroje než se spolehnout na default. Počet vláken lze nastavovat i klauzulí ``NUM_THREADS`` ve zdrojovém kódu programů, což je méně operativní a příliš závazné (mající přednost před proměnnou prostředí).
OpenMP programy škálují dobře (zvyšují výkon s počtem jader lineárně s faktorem 1) spíše vzácně; s rostoucím počtem zapojených jader se nemusí dostavit úměrné zvýšení výkonu. Nemusí pak být ekonomické věnovat běhu aplikace všechna jádra stroje. Lze uvážit vhodnost `trapné paralelizace `_ (zde: paralelní běh více aplikací běžících každá na nevelkém počtu jader). Negativní roli může hrát i možné snížení frekvence jader při zvýšeném zatížení (teplotě) procesoru; např. CPU `Intel i9-9900K `_ může s rostoucím zatížením snižovat frekvenci aktivních jader z 5.0 GHz na 3.6 GHz.