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.