Překlad a spouštění MPI úloh ---------------------------- MPI je na našich strojích v těchto implementacích: * default `Open MPI `_ pro `GNU `_ překladače, * (po ``source load_intel``) `Intel MPI `_ pro Intel a GNU překladače, * (po ``source load_nv``) `Open MPI `_ pro `Nvidia `_ překladače, * `MPICH `_ pro GNU překladače, plus nezávislé MPI implementace v dockerovských obrazech. Je vhodné používat MPI implementaci konzistentní s překladačem programu a volanými numerickými knihovnami. Při spouštění MPI úlohy na jediném stroji stačí určit počet procesů. Při spouštění MPI úlohy na více strojích je třeba nastavit bezheslový přístup, specifikovat hostitelské počítače a rozložení procesů na nich a specifikovat komunikační hardware a protokol. Vybrat lze rychlý `InfiniBand `_ (při QDR teoretických 32 Gbit/s), dostupný na *geofxyzw* a některých *geof.0*, nebo pomalejší `Ethernet `_ (1 Gbit/s), dostupný všude. Horní hranice přenosové rychlosti (*bandwidth*) může ve sdílené paměti našich strojů dosáhnout 10-20 GB/s, s InfiniBandem 3.5 GB/s a Ethernetem mírně nad 0.1 GB/s; rychlost významně závisí na velikosti předávaných dat, jak lze ověřit pomocí níže zmíněných MPI benchmarků. Open MPI (default) ^^^^^^^^^^^^^^^^^^ Default implementace MPI v Ubuntu 22.04 je Open MPI v4.1.2 vhodná pro GNU překladače v11. Programy se překládají pomocí *wrapperů* ``mpif90`` (nověji ``mpifort``) a ``mpicc``. Aktuální překladový řádek se odhalí příkazem ``mpif90 -show``, požadovaný překladač lze upřesnit pomocí proměnných prostředí ``OMPI_FC`` a ``OMPI_CC`` a přidat volby pro překlad pomocí proměnných ``OMPI_FCFLAGS`` a ``OMPI_CFLAGS`` nebo rovnou na řádku, např.:: # Open MPI Fortran compilation export OMPI_FCFLAGS="-Ofast -march=native" mpif90 file.f90 # using gfortran mpif90 -Ofast -march=native file.f90 # an alternative OMPI_FC=gfortran-12 mpif90 file.f90 # using gfortran v12 Úlohy se spouštějí pomocí *loaderu* ``mpirun`` (synonymum ``mpiexec``), obvykle s volbou ``-n`` (též ``-np``) udávající počet procesů. Pro běh procesů na jediném stroji není třeba zadávat víc, komunikace je implicitně vedena ovladačem sdílené paměti z komponenty ``ob1`` (výslovnost *Obi-Wan*, explicitně: ``-mca pml ob1 -mca btl self,vader``). Může být (stojí za test), že komunikace poběží o něco rychleji s užitím komponenty ``ucx`` (pouze na strojích s InfiniBandem):: # Open MPI local run mpirun -n 8 -mca pml ob1 a.out # point-to-point message layer: ob1 mpirun -n 8 -mca pml ucx a.out # point-to-point message layer: ucx mpirun -n 8 a.out # hosts with InfiniBand: ucx, without IB: ob1 Pro běh úloh na více strojích je nutné nastavit bezheslový přístup (viz níže Poznámky) a je vhodné připravit *hostfile* se seznamem hostitelů (co řádek, to jméno hostitele), přičemž stroje by si měly být podobné (např. všechny s InfiniBandem), popsat rozložení procesů na strojích (např. volbou ``-N`` pro počet procesů na každém stroji) a spouštět úlohy ve sdíleném adresáři zadaném absolutní cestou. Místo v *hostfile* lze seznam strojů a počty procesů na nich popsat v rámci volby ``-H``. Pomocí parametru ``-mca pml ucx`` se aktivuje UCX komunikace vhodná pro InfiniBand, komponentu ``ob1`` (píše se ``-mca pml ob1``) je pro InfiniBand možné využít také (v této variantě zvané `IPoIB `_ bývá méně výkonný). Na strojích bez InfiniBandu poskytuje komponenta ``ob1`` komunikaci přes Ethernet. S ``ob1`` je třeba explicitně zadávat jména adaptérů, u nás ``mib0`` pro InfiniBand a ``eno1`` pro Ethernet:: # Open MPI distributed run cd /AbsolutePath mpirun -n 16 -N 8 -hostfile hostfile -mca pml ucx a.out # hosts with InfiniBand mpirun -n 16 -N 8 -hostfile hostfile -mca pml ob1 -mca btl_tcp_if_include mib0 a.out # InfiniBand via IPoIB mpirun -n 16 -N 8 -hostfile hostfile -mca pml ob1 -mca btl_tcp_if_include eno1 a.out # Ethernet only MCA (*modular component architecture*) parametry loaderu lze nastavit trvaleji pomocí proměnných prostředí (máme to tak) a úlohy na více strojích pak spouštět jednodušším příkazem, zde včetně výčtu strojů s počty jejich procesů na příkazovém řádku místo v *hostfile*:: # Open MPI distributed run with predefined environment variables export OMPI_MCA_pml=ucx # hosts with InfiniBand export OMPI_MCA_pml=ob1 # hosts without InfiniBand export OMPI_MCA_btl_tcp_if_include=mib0 # hosts with InfiniBand export OMPI_MCA_btl_tcp_if_include=eno1 # hosts without InfiniBand cd /opt/osu-benchmarks/open-mpi/mpi/pt2pt # OSU benchmarks of MPI bandwidth, latency etc. mpirun -n 2 -H geofA:1,geofB:1 osu_bw Při nestandardním nastavení proměnných prostředí (typicky proměnné ``PATH``) na spouštějícím stroji může být nutné exportovat tyto proměnné poomcí volby ``-x``. Příkladem může být spouštění programu ``aspect``: cesta k němu se lokálně nastavuje voláním ``source load_aspect`` a takto změněnou hodnotu proměnné ``PATH`` je třeba explicitně distribuovat. :: # Open MPI distributed run with exported environment variables source load_aspect cd /AbsolutePath mpirun -x PATH -n 72 -H geofA:24,geofB:24,geocC:24 aspect file.prm # more variables: -x VAR1 -x VAR2 Pro ujištění, které MCA komponenty jsou aktivní, lze zvýšit *verbosity level* pomocí parametrů jako ``-mca pml_base_verbose 100``, ``-mca btl_base_verbose 100`` aj. Jejich přehled podává příkaz ``ompi_info -a``. Ověřit rozložení procesů na strojích lze volbou ``mpirun -display-map``. Intel MPI ^^^^^^^^^ Pro aktivaci MPI z Intel oneAPI HPC Toolkitu je určen místní příkaz ``source load_intel`` pro načtení Intel oneAPI konfigurace. Fortranské překladové *wrappery* jsou dva, ``mpiifort`` volající Intel Fortran a ``mpif90`` pro GNU Fortran, pro Intel C jsou určeny ``mpiicc`` a ``mpiicpc`` a pro GNU C ``mpicc`` a ``mpicxx``. Default volby *wrapper* přizná při volbě ``-show``, další volby pro překlad se přidají pomocí proměnných ``I_MPI_FCFLAGS`` a ``I_MPI_CFLAGS`` nebo rovnou na řádek (`více překladových proměnných `_):: # Intel MPI Fortran compilation source load_intel mpiifort file.f90 # using ifort mpiifort -Ofast -xHost file.f90 # with additional compiler options mpif90 file.f90 # using gfortran mpif90 -Ofast -march=native file.f90 # with additional compiler options Pro spouštění úloh lze použít loadery ``mpirun`` a ``mpiexec``, typicky s volbou ``-n`` (též ``-np``) udávající počet procesů. Volba komunikačního protokolu se provádí pomocí proměnné prostředí ``I_MPI_FABRICS``, její obvyklou hodnotou je ``shm:ofi`` (*shared memory* pro komunikaci uvnitř stroje, jinak ``ofi`` s *libfabric* knihovnou). Dodat proměnné prostředí příkazu lze i touto formou (`více běhových proměnných `_):: # Intel MPI local run source load_intel I_MPI_FABRICS=shm mpirun -n 8 ./a.out # local communication via shared memory I_MPI_FABRICS=ofi mpirun -n 8 ./a.out # local communication via ofi library Pro běh úloh na více strojích je nutné nastavit bezheslový přístup (viz níže Poznámky) a je vhodné připravit *hostfile* se seznamem hostitelů (co řádek, to jméno hostitele), popsat rozložení procesů na strojích (např. volbou ``-ppn``, *processes per node*, pro počet procesů na každém stroji) a spouštět úlohy ve sdíleném adresáři zadaném absolutní cestou. Pomocí proměnné ``I_MPI_OFI_PROVIDER`` se nastavuje OFI komunikace buď přes InfiniBand (``mlx`` = Mellanox), `IPoIB `_ (``tcp`` na strojích s InfiniBandem) nebo Ethernet (``tcp`` na strojích bez InfiniBandu):: # Intel MPI distributed run source load_intel cd /AbsolutePath I_MPI_OFI_PROVIDER=mlx mpirun -n 16 -ppn 8 -f hostfile ./a.out # hosts with InfiniBand I_MPI_OFI_PROVIDER=tcp mpirun -n 16 -ppn 8 -f hostfile ./a.out # hosts without InfiniBand S předdefinovanými proměnnými prostředí lze úlohy spouštět jednodušeji, zde včetně výčtu strojů na příkazovém řádku místo v *hostfile*:: # Intel MPI distributed run with predefined environment variables source load_intel export I_MPI_FABRICS=shm:ofi # default for both intra- and inter-node communication export I_MPI_OFI_PROVIDER=mlx # using fast InfiniBand export I_MPI_OFI_PROVIDER=tcp # using slower IPoIB or slow Ethernet cd /opt/osu-benchmarks/intel-mpi/mpi/pt2pt # OSU benchmarks of MPI bandwidth, latency etc. mpirun -n 2 -ppn 1 -hosts geofA,geofB ./osu_bw Diagnostiku lze vyžádat nastavením proměnné ``I_MPI_DEBUG`` na kladné hodnoty 1--100 (rozumná volba: 5). K dispozici je MPI profiler: nastaví se proměnná ``I_MPI_STATS`` na kladnou hodnotu 1--5 a po skončení běhu se získá statistika navrženým voláním příkazu ``aps`` (*application performance snapshot*). Open MPI pro Nvidia ^^^^^^^^^^^^^^^^^^^ Nvidia HPC Software Development Kit (SDK) obsahuje MPI implementace v.3 a v.4 vhodné pro Nvidia překladače. Pro aktivaci Open MPI v.4 je určen místní příkaz ``source load_nv``. Jména *wrapperů*, *loaderů* a proměnných odpovídají default Open MPI pro GNU překladače, viz tedy jejich popis výše. Nvidia Open MPI v.3 (místní příkaz ``source load_nv_mpi3``) nemá zabudovanou podporu UCX komunikace, pro InfiniBand (`IPoIB `_) lze použít komponentu ``ob1`` s adaptérem ``mib0``:: # Nvidia Open MPI run with predefined environment variables source load_nv # activation of Nvidia Open MPI v.4 export OMPI_MCA_pml=ucx # hosts with InfiniBand export OMPI_MCA_pml=ob1 # hosts without InfiniBand export OMPI_MCA_btl_tcp_if_include=mib0 # hosts with InfiniBand export OMPI_MCA_btl_tcp_if_include=eno1 # hosts without InfiniBand cd /opt/osu-benchmarks/open-mpi/mpi/pt2pt # OSU benchmarks of MPI bandwidth, latency etc. mpirun -n 2 osu_bw # local run mpirun -H geofA,geofB osu_bw # distributed run with Open MPI v.4, with and without InfiniBand source load_nv_mpi3 # activation of Nvidia Open MPI v.3 mpirun -H geofA,geofB -mca pml ob1 osu_bw # distributed run with Open MPI v.3, with InfiniBand mpirun -H geofA,geofB osu_bw # distributed run with Open MPI v.3, without InfiniBand MPICH ^^^^^ MPICH je implementace MPI konkurenční k Open MPI. V repozitářích Ubuntu ji lze nalézt a paralelizovaný software bývá nabízen jak pro Open MPI, tak pro MPICH. Na našich strojích je Open MPI nastaveno jako default, a tedy další software máme nachystán pro Open MPI. Ukáže-li se v ojedinělých případech problém s Open MPI, je možné obrátit se k MPICH. (Např. `Coarray Fortran `_ není v Ubuntu 22.04 schopen s Open MPI běhu na více strojích, s MPICH problém není.) Pro překlad a spouštění samostatných programů lze obdobně jako výše použít *wrappery* ``mpif90.mpich`` a ``mpicc.mpich`` a *loader* ``mpirun.mpich``. Volby těchto skriptů jsou většinou odchylné od voleb skriptů Open MPI; Intel MPI je odvozeno od MPICH, volby MPICH skriptů jsou tedy blízké výše popsaným volbám Intel MPI. Pro spojení s MPI paralelizovanými knihovnami je třeba mít tyto knihovny instalované ve verzi pro MPICH (nikoliv Open MPI). :: # MPICH Fortran compilation and run mpif90.mpich file.f90 # compilation using gfortran mpirun.mpich -n 8 ./a.out # local run mpirun.mpich -n 16 -ppn 8 -hosts geofA,geofB ./a.out # distributed run Obdobně jako výše lze volit např. ``mpif90 -show`` pro zjištění použitých voleb *wrapperu*. *Wrapper* ``mpif90.mpich`` je ekvivalentní s ``mpifort.mpich`` a *loader* ``mpirun.mpich`` je totéž co ``mpiexec.mpich``. Na volby *loaderu* se lze ptát příkazem ``mpirun.mpich -help``. Užitečná může být proměnná prostředí ``MPIEXEC_TIMEOUT``. Repozitářová MPICH knihovna je přeložena bez podpory UCX; dostupný komunikační protokol spolupracuje s InfiniBandem jen v podobě `IPoIB `_. Poznámky ^^^^^^^^ Pro bezheslové spojení mezi stroji je třeba na stroji A vytvořit soukromý a veřejný klíč pomocí ``ssh-keygen -t rsa`` (při potížích ``ssh-keygen -t ecdsa``). Vzniknou soubory ``~/.ssh/id_rsa`` a ``~/.ssh/id_rsa.pub``. Obsah druhého z nich se přidá na stroji B do souboru ``~/.ssh/authorized_keys``, čímž se povolí jednosměrný přístup z A na B. Přenos veřejného klíče je třeba provést všemi směry, které mají volné připojení umožnit. K adresáři ``~/.ssh`` smí mít právo k zápisu jen vlastník, jinak mohou být klíče nefunkční. Na strojích máme předdefinovány proměnné prostředí ``OMPI_MCA_pml``, ``OMPI_MCA_btl_tcp_if_include``, ``I_MPI_FABRICS`` a ``I_MPI_OFI_PROVIDER`` tak, aby se s Open MPI v.4 a Intel MPI přednostně využívala komunikace pomocí InfiniBandu. Pro ověření funkčnosti MPI systému a zvolených *runtime* parametrů lze využít sadu *OSU micro-benchmarks (Ohio State University)*, dostupnou v adresáři ``/opt/osu-benchmarks`` jak pro Open MPI, tak Intel MPI. K témuž účelu mohou posloužit také *Intel MPI benchmarks* v ``/opt/intel/oneapi/mpi/latest/benchmarks/imb``. .. Může být vhodné zrušit omezení na velikost zásobníku (*stack*) stanovenou v bashi: ``ulimit -s unlimited``. Na strojích s InfiniBandem je zrušena horní hranice pro registraci RDMA přístupu do paměti v uživatelských programech.