Komunikacja zbiorowa: część II

Slides:



Advertisements
Podobne prezentacje
Tablice 1. Deklaracja tablicy
Advertisements

Język C/C++ Funkcje.
Mechanizmy pracy równoległej
Wzorce.
Grażyna Mirkowska PJWSTK 15 listopad 2000
Język ANSI C Funkcje Wykład: Programowanie komputerów
Wykonał : Marcin Sparniuk
Metody rozwiązywania układów równań liniowych
Wykład 6 Najkrótsza ścieżka w grafie z jednym źródłem
Programowanie I Rekurencja.
PROGRAMOWANIE STRUKTURALNE
Sortowanie Zajęcia 13.
ZŁOŻONOŚĆ OBLICZENIOWA
ALGORYTMY GEOMETRYCZNE.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 7: Procedury i funkcje © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 8: Wykorzystanie procedur i funkcji © Jan Kaczmarek.
Materiały do zajęć z przedmiotu: Narzędzia i języki programowania Programowanie w języku PASCAL Część 5: Typy porządkowe, wyliczeniowe i okrojone. Definiowanie.
Podstawowe składniki funkcjonalne procesora i ich rola.
Tablice.
Systemy operacyjne Wykład nr 4: Procesy Piotr Bilski.
Tablice Informatyka Cele lekcji: Wiadomości: Uczeń potrafi:
Ogólne jednostki programowe 1
Dynamiczne struktury danych 1
Wykład 6 Standardowy błąd średniej a odchylenie standardowe z próby
Wykład 5 Przedziały ufności
Wykład 4 Przedziały ufności
Temat nr 10: System przerwań
Instytut Fizyki Teoretycznej
Instrukcja skoku GO TO etykieta Np. GO TO 100 ….. 100WRITE (*,*) Przeskok do instrukcji 100 Uwaga! NIE WOLNO skakać do wnętrzna złożonych instrukcji warunkowych.
Topologie wirtualne Topologia wirtualna: zadany schemat połączeń pomiędzy procesorami; inaczej mówiąc schemat ich wzajemnego sąsiedztwa. W MPI można określić.
Podstawy MPI-2: część II Dynamiczne zarządzanie procesami
Analiza kosztu zamortyzowanego
Semafory według normy POSIX
Podstawy programowania
Podstawy programowania II
Podstawy programowania
Podstawy programowania
Programowanie strukturalne i obiektowe
Równoległy algorytm metody Jacobiego rozwiązywania zagadanienia brzegowego dla eliptycznych równań różniczkowych cząstkowych.
Arkusze kalkulacyjne, część 3
Instrukcja USOSweb Wersja: Opracował: Sebastian Sieńko Moduł sprawdzianów.
Współczynnik przyspieszenia n - wielkość zadania p - liczba procesorów T(n,p) – czas wykonania.
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
JAVA c.d.. Instrukcji wyboru SWITCH używamy, jeśli chcemy w zależności od wartości pewnego wyrażenia wykonać jeden z kilku fragmentów kodu. Jest to w.
Inicjalizacja i sprzątanie
Przerwanie ang. interrupt.
Koncepcja procesu Zadanie i proces. Definicja procesu Process – to program w trakcie wykonywania; wykonanie procesu musi przebiegać w sposób sekwencyjny.
Farseer Physics Engine. Farseer Physics Engine jest silnikiem fizycznym napisanym dla platformy.NET. Został on zainspirowany przez silnik Box2D znany.
EXCEL Wykład 4.
Definiowanie typów danych użytkownika
Komendy SQL do pracy z tabelami i bazami
Wykład 10 typ zbiorowy rekurencja.
Wykład 7 Synchronizacja procesów i wątków
Projektowanie stron WWW
Temat 7: Instrukcje warunkowe
Metody numeryczne szukanie pierwiastka metodą bisekcji
Diagram aktywności (czynności)
Metody matematyczne w inżynierii chemicznej Wykład 3. Całkowanie numeryczne.
Kurs języka C++ – wykład 4 ( )
EXCEL Wstęp do lab. 4. Szukaj wyniku Prosta procedura iteracyjnego znajdowania niewiadomej spełniającej warunek będący jej funkcją Metoda: –Wstążka Dane:
Metody matematyczne w inżynierii chemicznej
Wykład 5 Przedziały ufności
Metody nieinkluzyjne: Metoda iteracji prostej.
Podział sieci IP na podsieci w ramach CISCO
Algorytmy. Co to jest algorytm? Przepis prowadzący do rozwiązania zadania.
Parametry rozkładów Metodologia badań w naukach behawioralnych II.
Algorytmy, sposoby ich zapisu.1 Algorytm to uporządkowany opis postępowania przy rozwiązywaniu problemu z uwzględnieniem opisu danych oraz opisu kolejnych.
Zbiory rozłączne.
Co do tej pory robiliśmy:
Haskell Składnia funkcji.
Zapis prezentacji:

Komunikacja zbiorowa: część II Najczęstsze błędy i wypaczenia przy stosowaniu komunikacji zbiorowej Grupy procesów i podział komunikatorów Operacje na grupach procesów Komunikacja wewnątrzgrupowa i komunikatory wewnętrzne Komunikacja międzygrupowa i komunikatory zewnętrzne

Błędy i wypaczenia w komunikacji zbiorowej Wywołanie procedury komunikacji zbiorowej tylko dla części procesorów zawartych w zaspecyfikowanym komunikatorze. W szczególności zapomnienie o tym, że w przypadku MPI_Bcast zarówno procesor źródłowy jak i wszyscy odbiorcy muszą zawołać tę procedurę. Założenie, że wszystkie procesory jednocześnie zakończą wykonywanie danej procedury komunikacji zbiorowej. Użycie tego samego bufora wejściowego i wyjściowego w wywołaniu MPI_Reduce (MPI_Allreduce).

1 i 2. Wywołanie w zależności od procesora (BARDZO POWAŻNY błąd, bo nie powoduje zatrzymania programu i przez to znakomicie utrudnia jego odrobaczenie). if (rank == 0) { MPI_Bcast(dane, ..., Master, ..., MPI_COMM_WORLD); do_masters_work(); else { do_work(dane,wyniki); MPI_Gather(wyniki,...,Master,...,MPI_COMM_WORLD); } W takim przypadku master wyśle dane do pozostałych procesorów ale dane te nigdy nie zostaną odebrane, natomiast wyniki wysłane przez robotników nigdy nie zostaną odebrane przez mastera. Należy napisać tak: else

4. Użycie tego samego bufora wejściowego i wyjściowego w MPI_Reduce call MPI_Allreduce(a, a, 1, MPI_REAL, MPI_SUM, comm, ierr); Spowoduje to natychmiastowy bład wykonania i przerwanie programu, więc błąd taki jest łatwy do wykrycia. Wymóg, aby bufor wyjściowy był różny od wyjściowego zapewnia kompatybilność ze standartem FORTRANu (przekazywanie zmiennej przez adres a nie przez wartość); w związku z tym ograniczenie obowiązuje również przy wołaniu MPI_Reduce w programach w C. Poprawny kod: call MPI_Allreduce(a, a_sum, 1, MPI_REAL, MPI_SUM, comm, ierr);

Grupy procesów i podział komunikatorów Grupa procesów: zbiór procesorów uporządkowany według rzędu. W MPI zdefiniowano „pustą” grupę: MPI_GROUP_EMPTY oraz dwie stałe: MPI_GROUP_EMPTY (odnośnik do grupy pustej) oraz MPI_GROUP_NULL (odnośnik do grupy zdefiniowanej niewłaściwie). Podział komunikatorów: Komunikatory wewnętrzne (intrakomunikatory): służą do komunikacji w obrębie grupy; możliwa jest komunikacja punktowa i zbiorowa. Komunikatory zewnętrzne (interkomunikatory): służą do komunikacji pomiędzy dwoma grupami. W standarcie MPI-1 możliwa jest jedynie komunikacja punktowa (MPI_Send i MPI_Receive).

Charakterystyka intra- i interkomunikatorów Funkcjonalność Intrakomunikator Interkomunikator Liczba grup 1 2 Bezpieczeństwo Tak Komunikacja zbiorowa Nie Topologie Kaszowanie

Operacje na grupach MPI_GROUP_SIZE(group, size): zwraca liczbę procesorów w grupie. MPI_Group_size(MPI_Group group, int *size) MPI_GROUP_SIZE(GROUP, SIZE, IERROR) INTEGER GROUP, SIZE, IERROR group - grupa size - liczba procesorów w grupie MPI_GROUP_RANK(group, rank): zwraca rząd danego procesora w grupie; jeżeli procesor nie jest w grupie jest zwracany rząd MPI_UNDEFINED. group - grupa rank - rząd procesora w grupie. MPI_Group_rank(MPI_Group group, int *rank) MPI_GROUP_RANK(GROUP, RANK, IERROR) INTEGER GROUP, RANK, IERROR

MPI_GROUP_TRANSLATE_RANKS(group1, n, ranks1, group2, ranks2) podaje rzędy procesorów z jednej grupy w innej grupie; w przypadku, gdy któryś z procesorów nie należy do drugiej grupy zwraca w tym miejscu MPI_UNDEFINED. group1 - grupa pierwsza n - liczba procesorów w tablicach ranks1 i ranks2 ranks1 - tablica rzędów w grupie pierwszej group2 - grupa druga ranks2 - tablica rzędów w grupie drugiej MPI_Group_translate_ranks (MPI_Group group1, int n, int *ranks1, MPI_Group group2, int *ranks2) MPI_GROUP_TRANSLATE_RANKS(GROUP1, N, RANKS1, GROUP2, RANKS2, IERROR) INTEGER GROUP1, N, RANKS1(*), GROUP2, RANKS2(*), IERROR

MPI_GROUP_COMPARE(group1, group2, result) porównuje dwie grupy zwracając wynik w zmiennej result: MPI_IDENT: grupy są identyczne; MPI_SIMILAR: grupy zawierają te same procesory ale w innym porządku; MPI_UNEQUAL: grupy są różne.

Kreatory grup MPI_COMM_GROUP(comm, group) uzyskiwanie wskaźnika grupy (group) odpowiadającej komunikatorowi comm. MPI_Comm_group(MPI_Comm comm, MPI_Group *group) MPI_COMM_GROUP(COMM, GROUP, IERROR) INTEGER COMM, GROUP, IERROR

Trzy standardowe operacje mnogościowe: MPI_GROUP_UNION(group1, group2, newgroup) MPI_GROUP_INTERSECTION(group1, group2, newgroup) MPI_GROUP_DIFFERENCE(group1, group2, newgroup)

MPI_GROUP_INCL(group, n, ranks, newgroup) tworzenie nowej grupy z elementów starej. group - stara grupa; n - liczba procesorów ze starej grupy, które mają być włączone do nowej; ranks - tablica zawierająca te rzędy; newgroup - nowa grupa. MPI_Group_incl(MPI_Group group, int n, int *ranks, MPI_Group *newgroup) MPI_GROUP_INCL(GROUP, N, RANKS, NEWGROUP, IERROR) INTEGER GROUP, N, RANKS(*), NEWGROUP, IERROR MPI_GROUP_EXCL(group, n, ranks, newgroup) tworzy nową grupę ze starej poprzez wyłączenie n procesorów o rzędach podanej w tablicy ranks. Składnia analogiczna do MPI_GROUP_INCL.

MPI_GROUP_RANGE_INCL(group, n, ranges, newgroup) MPI_GROUP_RANGE_EXCL(group, n, ranges, newgroup) Wygodniejsze formy poprzednich. Tablica ranges(3,*) zawiera zakresy włączanych/wyłączanych procesorów; ranges(1,i) i ranges(2,i) definiują odpowiednio pierwszy i ostatni procesorów w i-tym zakresie, ranges(3,i) mówi z jakim krokiem włącza/wyłącza się procesory (1 - każdy, 2 - co drugi, itd.). Destruktor grupy MPI_GROUP_FREE(group) MPI_Group_free(MPI_Group *group) MPI_GROUP_FREE(GROUP, IERROR) INTEGER GROUP, IERROR

Komunikacja wewnątrzgrupowa i komunikatory wewnętrzne Komunikacja wewnątrzgrupowa: wymiana informacji w obrębie procesorów należących do jednej grupy. Możliwe jest tutaj stosowanie zarówno procedur komunikacji punktowej jak i zbiorowej.

Operacje na komunikatorach MPI_COMM_SIZE(comm, size) MPI_COMM_RANK(comm, rank) MPI_COMM_COMPARE(comm1, comm2, result) Wartości zwracane przez MPI_COMM_COMPARE w zmiennej result są podobne jak w przypadku MPI_GROUP_COMPARE z wyjątkiem, że w przypadku identyczności grup odpowiadających komunikatorom comm1 i comm2 zwracana jest wartość MPI_CONGRUENT. Standardowe komunikatory MPI_COMM_WORLD: wszystkie procesory przydzielone zadaniu; MPI_COMM_SELF: dany procesor (zawsze ma rząd 0). MPI_COMM_NULL: pusty komunikator.

Kreatory komunikatorów MPI_COMM_DUP(comm, newcomm) tworzenie duplikatu komunikatora. comm - stary komunikator; newcomm - nowy komunikator. MPI_Comm_dup(MPI_Comm comm, MPI_Comm *newcomm) MPI_COMM_DUP(COMM, NEWCOMM, IERROR) INTEGER COMM, NEWCOMM, IERROR

MPI_COMM_CREATE(comm, group, newcomm) tworzenie („pączkowanie”) nowego komunikatora. comm - stary komunikator (może być MPI_COMM_WORLD); group - grupa procesorów, które mają utworzyć nowy komunikator; newcomm - nowy komunikator. int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newcomm) MPI_COMM_CREATE(COMM, GROUP, NEWCOMM, IERROR) INTEGER COMM, GROUP, NEWCOMM, IERROR

MPI_COMM_SPLIT(comm, color, key, newcomm) tworzenie nowych komunikatorów poprzez podział starego według przypisania zawartego w zmiennej color. comm - stary komunikator; color - kolor; procesory o różnych kolorach będą tworzyły różne komunikatory; key - klucz; wskazuje, jak ma wzrastać rząd procesorów (jeżeli dla dwóch procesorów w nowej grupie jest taki sam, kolejność rzędów jest tak jak kolejność rzędów w starej grupie); newcomm - nowy komunikator, w którym znajdzie się wywołujący procesor. Jeżeli nie chcemy, żeby dany procesor znalazł się w jakimkolwiek z nowych komunikatorów, nadajemy mu kolor MPI_UNDEFINED. MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm) MPI_COMM_SPLIT(COMM, COLOR, KEY, NEWCOMM, IERROR) INTEGER COMM, COLOR, KEY, NEWCOMM, IERROR

Rozważmy grupę procesorów a-j o rzędach (w starym komunikatorze) od 0-9 (┴ oznacza kolor MPI_UNDEFINED): rząd 1 2 3 4 5 6 7 8 9 procesor a b c d e f g h i j kolor      klucz ┴ ┴ Wywołanie MPI_COMM_SPLIT dla tego układu spowoduje powstanie trzech nowych komunikatorów: {f,g,a,d} (kolor 0); rzędy będą wynosiły odpowiednio 0, 1, 2, 3. {e,i,c} (kolor 3); rzędy będą wynosiły 0, 1, 2. {h} (kolor 5); rząd oczywiście 0. Procesory b oraz j nie będą należały do żadnego z komunikatorów.

Destruktor komunikatora MPI_COMM_FREE(comm) MPI_Comm_free(MPI_Comm *comm) MPI_COMM_FREE(COMM, IERROR) INTEGER COMM, IERROR

Przykład: Obliczanie liczby p metodą Monte Carlo Algorytm obliczania liczby p: losujemy pary liczb (x,y) należące do przedziału [-1..1] a następnie obliczamy przybliżenie ze stosunku liczby wylosowanych punktów leżących w kole scentrowanym w punkcie (0,0) i o promieniu 1 do liczby wszystkich wylosowanych punktów.

Dedykujemy procesor o najwyższym rzędzie jako serwer liczb losowych dla pozostałych procesorów. Z pozostałych procesorów tworzymy grupę przy pomocy procedury MPI_GROUP_EXCL oraz MPI_COMM_CREATE grupę „robotników” i definiujemy odpowiedni komunikator workers. „Robotnicy” obliczają ile przysłanych losowych punktów leży w kole (N_in) a ile poza nim (N_out), następnie wykorzystując procedurę MPI_ALLREDUCE działająca w obrębie komunikatora workers. Jeżeli obliczone przybliżenie liczby różni się od wartości prawdziwej o mniej niż zadeklarowaną dokładność (pobierana z linii polecenia) lub przekroczono maksymalną zadeklarowaną liczbę kroków, program się kończy. Jeżeli nie, każdy z „robotników” wysyła do serwera żądanie inicjalizacji generatora liczb losowych i procedura jest powtarzana od punktu 3. Kod źródłowy programu w języku C Wyniki (4 procesory)

Przykład zastosowania procedury MPI_Comm_split Źródło programu w C Wyniki

Komunikacja międzygrupowa Komunikacja międzygrupowa: wymiana informacji pomiędzy procesami należącymi do rozłącznych grup. Komunikację międzygrupową stosuje się dla zadań modularnych, gdzie informacje muszą przepływać pomiędzy kolejnymi grupami (rura) lub, w bardziej ogólnym przypadku, płynąć po grafie zdefiniowanym przez interkomunikatory.

Cechy komunikacji międzygrupowej: Można stosować jedynie procedury komunikacji punktowej. Pomiędzy grupami procesów definiuje się skierowane interkomunikatory; zbiór interkomunikatorów tworzy graf połączeń. Procesy identyfikuje się poprzez ich rzędy w lokalnych grupach.

Kreator interkomunikatorów MPI_INTERCOMM_CREATE(local_comm, local_leader, bridge_comm, remote_leader, tag, newintercomm) local_comm - komunikator lokalny local_leader - rząd procesora będącego „bazą” komunikatora lokalnego; musi być w bridge_comm bridge_comm - komunikator mostkujący; musi zawierać procesory obu łączonych grup (na ogół MPI_COMM_WORLD) remote_leader - rząd procesora-bazy komunikatora odległego (w bridge_comm) tag – „pieczątka” interkomunikatora newintercomm - nowo postały interkomunikator

MPI_Intercomm_create(MPI_Comm local_comm, int local_leader, MPI_Comm bridge_comm, int remote_leader, int tag, MPI_Comm *newintercomm) MPI_INTERCOMM_CREATE(LOCAL_COMM, LOCAL_LEADER, PEER_COMM, REMOTE_LEADER, TAG, NEWINTERCOMM, IERROR) INTEGER LOCAL_COMM, LOCAL_LEADER, PEER_COMM, REMOTE_LEADER, TAG, NEWINTERCOMM, IERROR

Tworzenie intrakomunikatora z dwóch interkomunikatorów MPI_INTERCOMM_MERGE(intercomm, high, newintracomm) intercomm - interkomunikator high - kolejność procesorów w tworzonej grupie newintracomm - utworzony intrakomunikator MPI_Intercomm_merge(MPI_Comm intercomm, int high, MPI_Comm *newintracomm) Sprawdzanie, czy komunikator jest intra- czy interkomunikatorem MPI_COMM_TEST_INNER(comm, flag) comm - komunikator flag - flaga; true jeżeli komunikator jest interkomunikatorem MPI_Comm_test_inter(MPI_Comm comm, int *flag)

Uzyskiwanie rozmiaru, rzędu procesora oraz grupy odpowiadającej „lokalnej” części interkomunikatora: MPI_COMM_RANK (comm, rank) MPI_COMM_SIZE (comm, size) MPI_COMM_GROUP (comm, group) Uzyskiwanie rozmiaru oraz grupy odpowiadającej „odległej” części interkomunikatora: MPI_COMM_REMOTE_SIZE (comm, size) MPI_COMM_REMOTE_GROUP (comm, group)

Przykład: Symulacja układu ocean: atmosfera call MPI_COMM_SIZE( MPI_COMM_WORLD, nprocs, ierr ) call MPI_COMM_RANK( MPI_COMM_WORLD, rank, ierr ) if (rank .lt. Size/2 ) then color = OCEAN else color = ATMOS endif call MPI_COMM_SPLIT( MPI_COMM_WORLD, color, rank, ocean_or_atmos_comm, ierr) call MPI_INTERCOMM_CREATE( ocean_or_atoms_comm, 0, MPI_COMM_WORLD, 0, 0, intercomm, ierr) if (color .eq. OCEAN) then ocean_comm = ocean_or_atmos_comm call do_ocean( ocean_comm ) atmos_comm = ocean_or_atmos_comm call do_atmos( atmos_comm ) call ocean_and_atmos( intercomm )

Przykład bardziej konkretny: przepływ danych pomiędzy grupami procesorów („rura”) Grupę 12 procesorów dzielimy na 3 podgrupy po 4 procesory w każdej, jak na rysunku. Dane są wymieniane w obie strony pomiędzy grupami 0 i 1 oraz 1 i 2. W tym celu dla grup 0 i 2 musimy zdefiniować po jednym komunikatorze, natomiast dla grupy 1 musimy zdefiniować 2 interkomunikatory - odpowiednio do komunikacji z grupą 0 i 2.

Źródło programu w C Wyniki (12 procesorów)