Komme igang med open-mpi og mpich2

Tue 03 July 2012

I denne artikkelen skal jeg ta for meg litt av de forskjellige begrepene man kommer bort i om man skal jobbe med programmering på flere prosesser.

Siden dette blir en mer praktisk artikkel tar jeg utgangspunk i at du har en Linux maskin tilgjengelig. Selv bruker jeg en maskin med Ubuntu 12.04 LTS, så alt er testet på dette systemet.

Det vi trenger for å komme igang er følgende:

  1. en kompilator (fortran / c / c++)
  2. en mpi pakke (mpich2 / open-mpi)
  3. en mpi wrapper
  4. en mpiexec / mpirun

Kompilatorer

Det finnes mange forskjellige typer kompilatorer men de mest aktuelle er gnu, portland group og intel. Siden gnucompilatorene er de eneste av disse tre som er gratis (intel har riktignok noen non-commercial versjoner tilgjengelig) så går vi for gnu i første omgang. Du finner disse i softwarecenter ved å søke på f.eks gfortran, eller du kan bruke kommandolinjen.

{code class="brush:bash"}

$ sudo apt-get install gfortran

For å sjekke at pakken har kommet inn som forventet.

{code class="brush:bash"}

$ gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

MPI Implementasjon

Akkurat som med kompilatorer finnes det forskjellige mpi pakker å velge mellom. MPI (message passing interface) er en standard som gjør at du kan kjøre programmene dine på flere prosessorer / hoster samtidig. For å lære mer om MPI kan du begynne å lese artikkelen MPI på wikpedia: http://en.wikipedia.org/wiki/Message_Passing_Interface

For å installere på vår Ubuntu maskin kan vi som vanlig bruke softwarecenter (mpich2, openmpi-common, openmpi-bin, openmpi-doc og evt openmpi-checkpoint), eller du kan installere de samme pakkene via kommandolinjen.

{code class="brush:bash"}

$ sudo apt-get install mpich2 openmpi-common openmpi-bin openmpi-doc openmpi-checkpoint

Merk at om du har følgt oppskriften over til punkt og prikke sitter du nå med to forskjellige implementasjoner av MPI, mpich og open-mpi. Disse skal i teorien være like, men i praksis er det både syntaksforskjeller og annet smårusk som gjør at man kan foretrekke den ene over den andre. Om du vet du klarer deg med kun en av implementasjonene gjør du enklest i å bare installere den ene du trenger. Forhåpentligvis skal jeg få listet opp noen av syntaksforskjellene i en senere artikkel når vi skal prøve å faktisk kompilere og kjøre paralell kode.

MPI Kompilatorer / MPI Wrappere

Nå som vi har kompilatorer og mpi på plass trenger vi wrappere. Mange kaller wrapperene for mpi-kompilatorer, men i praksis er det snarveier til de vanlige kompilatorene, hvor flagg og opsjoner for kompilering med mpistøtte er tatt med. Merk at dersom du har installert openmpi som beskrevet over har du ikke fått med wrapperene. Installer de via kommandolinjen.

{code class="brush:bash"}

$ sudo apt-get install libopenmpi-dev

om du har installert mpich2 trekker den automatisk med seg libmpich2-dev, og dermed også wrapperene for mpich2.

Så hva er egentlig denne wrapperen? Først lister vi ut alle wrapperene vi har tilgjengelige.

{code class="brush:bash"}

$ mpif
mpif77 mpif77.mpich2 mpif77.openmpi mpif90 mpif90.mpich2 mpif90.openmpi

mpif77 og mpif90 er snarveier til den av wrapperene som er default (enten mpif77.mpich2 eller mpif77.openmpi og tilsvarende for Fortran90 og e.v.t CPP om du har det).

du kan altså bruke en spesifikk wrapper ved å skrive den fullt ut. Eksempelvis mpif77.openmpi sikrer deg at du får openmpi uavhengig av om default på systemet er satt opp til mpich2 eller openmpi.

Hvordan sjekker jeg hvilken wrapper som er default? Dette styres av debian sitt update-alternatives system.

{code class="brush:bash"}

$ update-alternatives --display mpi

mpi - auto modus
lenke peker for øyeblikket til /usr/include/mpich2

... mye tekst kommer her...

Nåværende «beste» versjon er «/usr/include/mpich2».

Men hva var nå denne wrapperen egentlig for noe? Ved å kjøre de med switchen -show ser vi hva som egentlig skjer.

{code class="brush:bash"}

$ mpif77 -show
gfortran -Wl,-Bsymbolic-functions -Wl,-z,relro -I/usr/include/mpich2 -L/usr/lib -lmpich -lopa -lmpl -lrt -lcr -lpthread

$ mpif77.openmpi -show
gfortran -I/usr/lib/openmpi/include -pthread -L/usr/lib/openmpi/lib -lmpi_f77 -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl

Husk at den første kommandoen 'mpif77 -show' tilsvarer 'mpif77.mpich2 -show' siden mpich2 er gjeldende mpi implementasjon ifølge update-alternatives.

Om du ikke ønsker å bruke wrapperene kan du skrive ut hele linjen som kom etter -show, men da vil jeg påstå at wrapperen er mest behagelig å forholde seg til. Det finnes måter å endre wrapper flagg på også, men det er ikke noe jeg går inn på i en introduksjonsartikkel.

MPI Run / MPI Exec

Som endel av installasjonen av mpiimplementasjonene har vi også fått det vi trenger for å eksekvere våre paralelle programmer. Igjen kan vi sjekke hva vi har tilgjengelig, og hvilken som er satt som default.

{code class="brush:bash"}

$ update-alternatives --display mpirun
mpirun - auto modus
lenke peker for øyeblikket til /usr/bin/mpirun.openmpi
/usr/bin/mpirun.mpich2 - prioritet 40
slave mpiexec: /usr/bin/mpiexec.mpich2
slave mpiexec.1.gz: /usr/share/man/man1/mpiexec.mpich2.1.gz
slave mpirun.1.gz: /usr/share/man/man1/mpirun.mpich2.1.gz
/usr/bin/mpirun.openmpi - prioritet 50
slave mpiexec: /usr/bin/mpiexec.openmpi
slave mpiexec.1.gz: /usr/share/man/man1/mpiexec.openmpi.1.gz
slave mpirun.1.gz: /usr/share/man/man1/mpirun.openmpi.1.gz
Nåværende «beste» versjon er «/usr/bin/mpirun.openmpi».

Akurat som med wrapperene kan vi kjøre programmene ved å oppgi det fulle navnet på implementasjonen vi vil bruke 'mpirun.openmpi' og 'mpirun.mpich2', eller om vi ønsker å bruke den defaulte 'mpirun' (i eksempelet over mpich2 versjonen).

Oppsummering

Jeg har nå gått raskt igjennom hva du trenger for å komme igang med mpi og paralellisering. Jeg har tatt utgangspunkt i et standard Ubuntu 12.04 LTS system. Det eneste som mangler nå er kode som vi kan kjøre i paralell. Jeg skal prøve å komme tilbake til en artikkel med enkle eksempler på kode som kan kjøre i paralell, samt vise hvordan vi kan kompilere den opp og eksekvere den på flere samtidige prosessorer / hoster ved hjelp av mpirun.

Comments