MPICH
Z Wikipedii
MPICH to ogólnodostępna, darmowa i przenośna implementacja standardu MPI. Pozwala na przekazywanie komunikatów pomiędzy aplikacjami działającymi równolegle. Nadaje się do stosowania na małych klastrach.
Najnowszą wersję biblioteki MPICH można pobrać ze strony domowej projektu. Biblioteki MPICH można używać zarówno na systemach klasy MS Windows jak i Unix.
Rozwinięciem MPICH jest MPICH2.
Powstała także wersja tej biblioteki o nazwie MPICH-G2 pozwalająca uruchamiać aplikacje równoległe w środowiskach gridowych, z wykorzystaniem pakietu Globus Toolkit jako warstwy pośredniej. Dzięki temu rozwiązaniu aplikacja może działać na kilku klastrach rozproszonych geograficznie.
Spis treści |
[edytuj] Charakterystyka
MPICH jest implementacją biblioteki sterowania procesem obliczeń równoległych na maszyny klasy PC. Protokół ten przeznaczony jest do sterowania procesem obliczeń równoległych w sieciach rozproszonych. Biblioteka procedur MPICH jest dostępna bezpłatnie. Najnowsza wersja tej biblioteki MPICH2 poza zapewnieniem bardziej wydajnych mechanizmów komunikacji posiada dodatkowo:
- wsparcie dla komunikacji jednostronnej
- rozszerzoną funkcjonalność MPI-IO
[edytuj] Instalacja
Opis instalacji MPICH (jednej z implementacji MPI)
1. Na początku należy pobrać źródła programu : mpich.tar.gz
2. Rozpakowujemy plik mpich.tar.gz
# tar xfz mpich.tar.gz
3. Będąc w katalogu /mpich wydajemy komendę:
# ./configure --prefix=/opt/mpich
--prefix=/opt/mpich - określa ścieżkę docelową dla MPICH
4. Kompilujemy program wydając komendę:
# make
5. Dokonujemy instalacji w katakogu podanym w opcji prefix:
# make install
[edytuj] Konfiguracja
Konfiguracja MPICH
W pliku machines.LINUX (katalog: /opt/mpich/share lub inny wybrany w opcji prefix podczas instalacji) dopisujemy nazwy hostów wchodzacych w skład klastra:
hostname1:liczba_procesów
hostname2:liczba_procesów
hostname3:liczba_procesów
gdzie:
- hostname - oznacza nazwa komputera wchodzącego w skład klastra,
- liczba_procesów - liczba procesorów danego hosta
[edytuj] Przesyłanie komunikatów
[edytuj] Komunikacja punkt - punkt
[edytuj] Przykład
Przykład komunikacji międzyprocesowej typu punkt-punkt. Zadaniem programu jest przesłanie komunikatu o treści "Komunikat od procesu 0" z procesu o numerze rank = 0 (SOURCE) do procesu o numerze rank = 1 (DEST).
#include <stdio.h> #include "mpi.h"
#define TAG 0 #define COUNT 25 #define SOURCE 0 #define DEST 1
int main(int argc, char *argv[]) { int rank, size; MPI_Status status;
char Msg[]="Komunikat od procesu 0"; // treść komunikatu przesyłanego między procesami char Recv[COUNT]; MPI_Init(&argc,&argv); // inicjalizacja środowiska MPI manual MPI_Comm_size(MPI_COMM_WORLD,&size); // ilość procesów w grupie zapisywana jest w zmiennej size manual MPI_Comm_rank(MPI_COMM_WORLD,&rank); // rank bieżącego procesu zapisywany jest w zmienej rank manual
if (size > 1) { // sprawdzane jest czy istnieje minimalna liczba procesów
// Komunikat przesyłany jest od procesu o numerze rank = 0 (SOURCE) // do procesu o numerze rank = 1 (DEST) if (rank == DEST) // jeżeli procesem jest proces odbierajacy komunikat: { printf ("process %d of %d waiting for message from %d\n", rank, size, SOURCE); // odbiór komunkatu i zapis zawartości do bufora Recv manual MPI_Recv(Recv, COUNT, MPI_CHAR, SOURCE, TAG, MPI_COMM_WORLD, &status); printf ("process %d of %d has received: '%s'\n", rank, size, Recv); }
else
if (rank == SOURCE) // jeżeli procesem jest proces nadający komunikat: { printf ("process %d of %d sending '%s' to %d\n", rank, size, Msg, DEST); // wysyłanie komunkatu zawartego w buforze Msg manual MPI_Send(Msg, COUNT, MPI_CHAR, DEST, TAG, MPI_COMM_WORLD); } } MPI_Finalize(); // zakończenie wykonywania procesów MPI manual return 0; }
Program kompiluje się wprowadzając polecenie:
# mpicc -o program_mpi program_mpi.c
[edytuj] Komunikacja grupowa
MPICH dostarcza kilku funkcji, ułatwiających komunikowanie się "na raz", ze wszystkimi procesami w grupie. Poza sporym ułatwieniem zapewniają one (a raczej zapewnia to MPICH) ,że dane zostaną przesłane w optymalny sposób (naiwny broadcast(iteracja) vs. MPI_Bcast(algorytm "drzewiasty") ).
[edytuj] MPI_Bcast
Rozsyła komunikat do wszystkich procesów w grupie.
int vsize = 4; float vect[vsize]; ... int status = MPI_Bcast( vect ,vsize ,MPI_FLOAT ,0 /*root*/ , MPI_COMM_WORLD); // man
[edytuj] MPI_Scatter
Funkcja dzieli wektor danych wejściowych (w procesie oznaczonym jako root) i rozysła je tak ,że procesowi o randze N jest przesyłana N-ta część wektora danych.
int vsize = 4; float matrix[vsize*vsize]; float rvect[vsize] int status = MPI_Scatter(matrix, vsize, MPI_FLOAT, rvect, vsize, MPI_FLOAT, 0 /*root*/, MPI_COMM_WORLD); // do 4-ech procesów!!! man
[edytuj] MPI_Gather
Funkcja odwrotna do MPI_Scatter. Zbiera dane w procesie oznaczonym root. Ustawia je w kolejkę zgodnie z rangą nadsyłającego procesu.
int vsize = 4; float matrix[vsize*vsize]; float rvect[vsize] int status = MPI_Gather(rvect, vsize, MPI_FLOAT, matrix, vsize, MPI_FLOAT, 0 /*root*/ ,MPI_COMM_WORLD); // od 4-ech procesów !!!man
[edytuj] MPI_Reduce
Funkcja wykonuje zdefiniowaną operację na wysłanych przez procesy danych. Możliwe operacje:
- MPI_MAX - maximum
- MPI_MIN - minimum
- MPI_SUM - suma
- MPI_PROD - produkt
- MPI_LAND - logiczny AND
- MPI_LOR - logiczny OR
- MPI_LXOR - logiczny XOR
- MPI_BAND - bitowy AND
- MPI_BOR - bitowy OR
- MPI_BXOR - bitowy XOR
int val = 1, procCnt; int status = MPI_Reduce( &val ,&procCnt ,1 ,MPI_INT ,MPI_SUM ,0 /*root*/ ,MPI_COMM_WORLD ); // alternatywna metoda liczenia procesów :) man
[edytuj] Przykład
Przykład komunikacji grupowej realizowanej za pośrednictwem funkcji MPI_Scatter i MPI_Reduce.
Działanie programu polega na rozesłaniu poszczególnych wierszy macierzy zawartej w buforze sendbuf do czterech procesów w grupie.
#include "mpi.h" #include <stdio.h> #define SIZE 4
main(int argc, char *argv[]) { int numtasks, rank, sendcount, recvcount, source; float sendbuf[SIZE][SIZE] = { {1.0, 2.0, 3.0, 4.0}, {5.0, 6.0, 7.0, 8.0}, {9.0, 10.0, 11.0, 12.0}, {13.0, 14.0, 15.0, 16.0} }; // inicjalizacja bufora do wysyłki float recvbuf[SIZE];
MPI_Init(&argc,&argv); // inicjalizacja środowiska MPI manual MPI_Comm_rank(MPI_COMM_WORLD, &rank); // rank bieżącego procesu zapisywany jest w zmienej rank manual MPI_Comm_size(MPI_COMM_WORLD, &numtasks); // ilość procesów w grupie zapisywana jest w zmiennej size manual
if (numtasks == SIZE) { // jeżeli w grupie są dokładnie 4 procesy: source = 1; sendcount = SIZE; recvcount = SIZE;
// rozsyłanie do procesów w grupie komunikatu zawartego w buforze sendbuf manual MPI_Scatter(sendbuf,sendcount,MPI_FLOAT,recvbuf,recvcount, MPI_FLOAT,source,MPI_COMM_WORLD);
printf("rank= %d Results: %f %f %f %f\n",rank,recvbuf[0], recvbuf[1],recvbuf[2],recvbuf[3]); int val = 1, procCnt; MPI_Reduce( &val ,&procCnt ,1 ,MPI_INT ,MPI_SUM ,source ,MPI_COMM_WORLD ); // suma ,czyli liczba procesów man } else printf("Must specify %d processors. Terminating.\n",SIZE);
MPI_Finalize(); // zakończenie wykonywania procesów MPI manual }
Program kompiluje się wprowadzając polecenie:
# mpicc -o program_mpi program_mpi.c