Podstawy MPI-2: część I Literatura: Using MPI-2. Advanced Features of the Message-Passing Interface, W. Gropp, E. Lusk, R. Thakur, MIT Press, Cambridge,

Slides:



Advertisements
Podobne prezentacje
C++ wykład 2 ( ) Klasy i obiekty.
Advertisements

C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Polska Infrastruktura Informatycznego Wspomagania Nauki w Europejskiej Przestrzeni Badawczej Intuicyjny interfejs do zasobów projektu PL-Grid Migrating.
Mechanizmy pracy równoległej
1 Dzisiejszy wykład Wzorce funkcji Wzorce klas. 2 Wzorce Często pojawia się konieczność pisania podobnych funkcji lub klas operujących na argumentach.
Wzorce.
Programowanie I Rekurencja.
SYSTEMY OPERACYJNE WSTĘP
Systemy rozproszone W. Bartkiewicz
PROGRAMOWANIE STRUKTURALNE
Grafika komputerowa Wykład 2 Wykorzystanie podstawowych usług bibliotecznych (API) w operacjach graficznych.
Serwery Aplikacji ASP .NET Web Objects Arkadiusz Popa.
Programowanie imperatywne i język C Copyright, 2004 © Jerzy R. Nawrocki Wprowadzenie.
LITERATURA M.Ben-Ari, Podstawy programowania współbieżnego i rozproszonego, WN-T, 1996 I.Foster, Designing and Building parallel programs, Cocepts and.
Systemy operacyjne Wykład nr 4: Procesy Piotr Bilski.
Biblioteki i przestrzenie nazw
C++ wykład 2 ( ) Klasy i obiekty.
Magistrala & mostki PN/PD
Instytut Fizyki Teoretycznej
Wykład 2 struktura programu elementy języka typy zmienne
Podstawy MPI-2: część II Dynamiczne zarządzanie procesami
Język Java Wielowątkowość.
Semafory według normy POSIX
Modele baz danych - spojrzenie na poziom fizyczny
Pamięć wspólna Opis własnego rozwiązania Marcin Kamiński, Michał Kotra Wydział EAIiE Katedra Automatyki Kraków, 2008.
Zastosowanie technologii CUDA w sztucznej inteligencji
Komputery macierzowe.
Pakiety w Javie Łukasz Smyczyński (132834). Czym są pakiety? Klasy w Javie są grupowane w pewne zbiory zwane pakietami. Pakiety są więc pewnym podzbiorem.
Podstawy programowania II
Podstawy programowania II Wykład 2: Biblioteka stdio.h Zachodniopomorska Szkoła Biznesu.
Podstawy programowania II
Programowanie w języku Matlab
Równoległy algorytm metody Jacobiego rozwiązywania zagadanienia brzegowego dla eliptycznych równań różniczkowych cząstkowych.
Zasada działania komputera
SYSTEMY OPERACYJNE I SIECI KOMPUTEROWE
Współczynnik przyspieszenia n - wielkość zadania p - liczba procesorów T(n,p) – czas wykonania.
Automatyka i Robotyka Systemy czasu rzeczywistego Wykład 4.
Jerzy F. Kotowski1 Informatyka I Wykład 14 DEKLARATORY.
Programowanie obiektowe – zastosowanie języka Java SE
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.
Koncepcja procesu Zadanie i proces. Definicja procesu Process – to program w trakcie wykonywania; wykonanie procesu musi przebiegać w sposób sekwencyjny.
EXCEL Wykład 4.
POŚREDNIK Jak reprezentowana jest informacja w komputerze? liczby – komputer został wymyślony jako zaawansowane urządzenie służące do wykonywania.
Definiowanie typów danych użytkownika
Podstawy informatyki 2013/2014
Użytkowanie i programowanie Matlaba
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
Systemy operacyjne (wiosna 2014)
Systemy rozproszone  Rozdzielenie obliczeń między wiele fizycznych procesorów.  Systemy luźno powiązane – każdy procesor ma lokalną pamięć; procesory.
System plików.
Kurs języka C++ – wykład 4 ( )
Procesy, wątki Program a proces Proces: Przestrzeń adresowa, kod, dane, stos (część pamięci do przechowania zmiennych lokalnych i niektórych adresów) Otwarte.
MPI: podstawy i komunikacja punktowa. Charakterystyka standardowego interfejsu przesyłania wiadomości MPI: Kod jest napisany w „zwyczajnym” języku programowania.
1 An Introduction to MPI Parallel Programming with the Message Passing Interface William Gropp Ewing Lusk Argonne National Laboratory Wprowdzenie do MPI.
Waldemar Bartyna 1 Programowanie zaawansowane LINQ to XML.
Komunikacja zbiorowa – część I Komunikacja zbiorowa: przesyłanie danych pomiędzy wszystkimi procesorami grupy zdefiniowanymi przez dany komunikator. Typy.
Podsumowanie wiedzy MPDI2 sem.3 INFORMATYKA. tworzenie nowego pliku i katalogu, nawigacja po katalogach, listowanie zawartości katalogu, zmiana nazw,
Model warstwowy ISO-OSI
Tryby adresowania i formaty rozkazów mikroprocesora
Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego Matuszyka Podstawy.
ASP.NET Dostęp do bazy danych z poziomu kodu Elżbieta Mrówka-Matejewska.
K URS JĘZYKA C++ – WYKŁAD 3 ( ) Przenoszenie Składowe statyczne Funkcje wbudowane Argumenty domyślne.
Wątki, programowanie współbieżne
(według:
Programowanie Obiektowe – Wykład 2
ETO w Inżynierii Chemicznej
Język C++ Typy Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła Jerzego.
Modele baz danych - spojrzenie na poziom fizyczny
Zapis prezentacji:

Podstawy MPI-2: część I Literatura: Using MPI-2. Advanced Features of the Message-Passing Interface, W. Gropp, E. Lusk, R. Thakur, MIT Press, Cambridge, Przykłady są dostępne na sieci pod Prezentacja “Introduction to parallel I/O and MPI-IO”, R. Thakur, ANLIntroduction to parallel I/O and MPI-IO Tutorial “Rozszerzenia standardu MPI” na stronie Poznańskiego Centrum Sieciowo-Superkomupterowego.“Rozszerzenia standardu MPI” MPI Forum (

Historia 1992: Pierwsze spotkanie MPI Forum na konferencji Supercomputing ‘92. Początek prac nad standardem MPI : Pierwsze wydanie książki “Using MPI” pomaga przekonać programistów równoległych do tego standardu. Użytkownicy PVM wskazują jednak na brak możliwości dynamicznej alokacji procesów, wszyscy użytkownicy wskazują na konieczność równoległych operacji I/O a CRAY- T3D (biblioteka shmem) i CM-5 udowadniają użyteczność jednostronnych operacji na pamięci. 1995: spotkanie MPI-2 Forum i ponowne podjęcie prac nad standardem MPI. Trochę zmodyfikowany standard MPI : MPI-2 dostępna dla użytkowników.

Nowe rzeczy w MPI-2 Główne modyfikacje (“wielka trójka”) Równoległe operacje wejścia/wyjścia. Operacje na pamięci odległej. Dynamiczne zarządzanie procesami Pomniejsze modyfikacje Specyfikacje zewnętrznych interfejsów. Połączenie z C++ i Fortranem 90. Wątki. Łączenie modułów w różnych językach. Rozszerzone operacje komunikacji zbiorowej (np. na interkomunikatorach).

Równoległe operacje wejścia/wyjścia MPI-IO Pisanie do pliku jest wysłaniem wiadomości do systemu plików; narzędzia do tego celu już są w MPI. Podstawowe funkcje MPI-IO: –open, –close, –seek, –read, –write Argumenty tych funkcji są podobne jak w UNIXowym I/O.

Cechy operacji MPI-IO Rozproszenie pamięci oraz rekordów pliku. Zbiorowe operacje I/O. Niewstrzymuące operacje I/O. Specyfikacja offsetu położenia rekordu w pliku w celu uniknięcia oddzielnych operacji seek. Lokalne i globalne wskaźniki plików. Reprezentacje danych przenaszalne i możliwe do definiowania przez użytkownika. Wskazówki dla implementacji i systemu plików.

Operacje na pamięci odległej Model przesyłania wiadomości: dane są przesyłane przy użyciu pary send/receive. Model pamięci wspólnej: procesory mają dostęp do wspólnej części pamięci i mogą pobierać lub umieszczać w niej dane. W MPI-2 zdefiniowano operacje put, get i collect, które umożliwiają dostęp do pamięci innego procesora w sposób analogiczny do modelu pamięci wspólnej. Te operacje określa się mianem operacji na pamięci odległej, zdalnych operacji na pamięci lub jednostronnych operacji na pamięci (ang. “one-sided” lub “remote memory” operations). Pamięć dostępną dla innego procesora specyfikuje się jako okno pamięci (window).

Cechy operacji na pamięci odległej w MPI-2 Zrównoważenie efektywności i przenaszalności między różnymi architekturami, włączając maszyny SMP (Shared Memory multiProcessors), NUMA (NonuUiform Memory Access), MPP (distributed memory Massively Parallel Processors), klastry SMP, czy sieci heterogeniczne. Zachowanie “spojrzenia i czucia” (look and feel) MPI. Uwzględnienie subtelnych różnic zachowania pamięci takich, jak koherencja pamięci cache, zgodność sekwencyjna, itp. Oddzielenie synchronizacji od przesyłania danych w celu zwiększenia efektywności.

Dynamiczne zarządzanie procesami W MPI-2 dany proces może –uczestniczyć w tworzeniu nowego procesu MPI (operacja rozmnażania; ang. spawning), –nawiązać komunikację z procesami wystartowanymi oddzielnie (operacja połączenia). Główe cele przy projektowaniu takiego API (Application Programing Interface): –Utrzymanie prostoty i elastyczności. –Interakcja z systemem operacyjnym, zarządcą zasobów, procesu oraz złożonym otoczeniem programowym. –Unikanie efektu “wyścigu” źle wpływającego na dokładność. Aby osiągnąć te cele, operacje zarządzania pamięcią muszą być zbiorowe, zarówno w obrębie procesów macierzystych jak i potomych. Procesy potomne są reprezentowane przez interkomunikatory.

MPI-IO

Sekwencyjne I/O w programie równoległym Master plik Pamięć Procesor Pisze/czyta tylko master, który odpowiednio zbiera dane od innych procesorów lub rozsyła do nich przeczytane dane.

MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); for (i=0; i<BUFSIZE; i++) buf[i] = myrank * BUFSIZE + i; if (myrank != 0) MPI_Send(buf, BUFSIZE, MPI_INT, 0, 99, MPI_COMM_WORLD); else { myfile = fopen("testfile", "w"); fwrite(buf, sizeof(int), BUFSIZE, myfile); for (i=1; i<numprocs; i++) { MPI_Recv(buf, BUFSIZE, MPI_INT, i, 99, MPI_COMM_WORLD, &status); fwrite(buf, sizeof(int), BUFSIZE, myfile); } fclose(myfile); } Przykład pisania tylko przez mastera

Zalety takiej organizacji pisania/czytania Maszyna na której chodzi program równoległy może dopuszczać I/O tylko z jednego albo ograniczonej liczby procesów lub znacznie ograniczać wydajność jeżeli każdy procesor pisze do oddzielnego pliku na wspólnym systemie plików (np. bigben w PSC czy galera w TASKu). Można używać zaawansowanych nierównoległych bibliotek I/O (np. biblioteki zarządzania danymi). Wszystkie wyniki są w jednym pliku, na którym takie operacje jak ftp, cp, mv są łatwiejsze i szybsze niż na wielu. Wady Obniżanie efektywności kodu poprzez sekwencyjność operacji pisania/czytania i konieczność przesyłania danych.

Równoległe nie-MPI I/O w programie równoległym plik Pamięć Procesor Każdy procesor pisze do oddzielnego pliku albo niezależnie czyta z tego samego lub oddzielnego pliku

Przykład pisania przez każdy procesor do oddzielnego pliku o nazwie zawierającej rząd procesora MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); for (i=0; i<BUFSIZE; i++) buf[i] = myrank * BUFSIZE + i; sprintf(filename, "testfile.%d", myrank); myfile = fopen(filename, "w"); fwrite(buf, sizeof(int), BUFSIZE, myfile); fclose(myfile); MPI_Finalize(); return 0; W FORTRANie rząd procesora można umieścić w nazwie pliku przez pisanie do łańcucha, np. character*64 fname …….. write (fname,'(2a,bz,i3.3)') ‘plik_',taskid

Zalety takiego podejścia Operacje I/O są równoległe ale mogą korzystać z sekwencyjnych bibliotek I/O. Wady Często pliki wyprodukowane przez poszczególne procesory trzeba łączyć w jeden do dalszego przetwarzania. Program używających te pliki jako pliki danych często sam musi być równoległy i chodzić na tej samej liczbie procesorów co program, który je wyprodukował. Uciążliwość w “ogarnięciu” i wykonywaniu opearacji takich jak cp, mv, ftp na dziesiątkach a nawet tysiącach małych plików. Pojawianie się nieoczekiwanych błędów przy jednoczesnym czytaniu jednego dużego pliku danych przez wiele procesorów.

Kod piszący wyniki do wielu plików z użyciem MPI-IO MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); for (i=0; i<BUFSIZE; i++) buf[i] = myrank * BUFSIZE + i; sprintf(filename, "testfile.%d", myrank); MPI_File_open(MPI_COMM_SELF, filename, MPI_MODE_WRONLY | MPI_MODE_CREATE, MPI_INFO_NULL, &myfile); MPI_File_write(myfile, buf, BUFSIZE, MPI_INT, MPI_STATUS_IGNORE); MPI_File_close(&myfile); MPI_Finalize();

MPI_FILE_OPEN(comm, filename, amode, info, fh) [ IN comm] komunikator (handle) [ IN filename] nazwa pliku (string) [ IN amode] tryb dostępu do pliku (integer) [ IN info] obiekt info (handle) [ OUT fh] “pokrętło” utworzonego pliku (handle) C: int MPI_File_open(MPI_Comm comm, char *filename, int amode, MPI_Info info, MPI_File *fh) FORTRAN/FORTRAN 90: MPI_FILE_OPEN(COMM, FILENAME, AMODE, INFO, FH, IERROR) CHARACTER*(*) FILENAME INTEGER COMM, AMODE, INFO, FH, IERROR C++: static MPI::File MPI::File::Open(const MPI::Intracomm& comm, const char* filename, int amode, const MPI::Info& info)

MPI_FILE_WRITE(fh, buf, count, datatype, status) [ INOUT fh] “pokrętło” pliku (handle) [ IN buf] początkowy adres buforu (choice) [ IN count] liczba elementów danych w buforze (integer) [ IN datatype] typ każdego elementu danych (handle) [ OUT status] obiekt stanu (Status) C: int MPI_File_write(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) FORTRAN/FORTRAN90: MPI_FILE_WRITE(FH, BUF, COUNT, DATATYPE, STATUS, IERROR) BUF(*) INTEGER FH, COUNT, DATATYPE, STATUS(MPI_STATUS_SIZE), IERROR C++: void MPI::File::Write(const void* buf, int count, const MPI::Datatype& datatype, MPI::Status& status) void MPI::File::Write(const void* buf, int count, const MPI::Datatype& datatype)

MPI_FILE_CLOSE(fh) [ INOUT fh] “pokrętło” pliku (handle) C: int MPI_File_close(MPI_File *fh) FORTRAN/FORTRAN90: MPI_FILE_CLOSE(FH, IERROR) INTEGER FH, IERROR C++: void MPI::File::Close()

Schemat równoległego pisania/czytania z tego samego pliku przez wiele procesorów. Każdy procesor ma w danej chwili dostęp do innej części pliku. plik Pamięć Procesor

Kod piszący wyniki do jednego pliku z użyciem MPI-IO: C MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); for (i=0; i<BUFSIZE; i++) buf[i] = myrank * BUFSIZE + i; MPI_File_open(MPI_COMM_WORLD, "testfile", MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &thefile); MPI_File_set_view(thefile, myrank * BUFSIZE * sizeof(int), MPI_INT, MPI_INT, "native", MPI_INFO_NULL); MPI_File_write(thefile, buf, BUFSIZE, MPI_INT, MPI_STATUS_IGNORE); MPI_File_close(&thefile); MPI_Finalize();

Kod piszący wyniki do jednego pliku z użyciem MPI-IO: FORTRAN90 call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr) do i = 0, BUFSIZE buf(i) = myrank * BUFSIZE + i enddo call MPI_FILE_OPEN(MPI_COMM_WORLD, 'testfile', & MPI_MODE_WRONLY + MPI_MODE_CREATE, & MPI_INFO_NULL, thefile, ierr) ! assume 4-byte integers disp = myrank * BUFSIZE * 4 call MPI_FILE_SET_VIEW(thefile, disp, MPI_INTEGER, & MPI_INTEGER, 'native', & MPI_INFO_NULL, ierr) call MPI_FILE_WRITE(thefile, buf, BUFSIZE, MPI_INTEGER, & MPI_STATUS_IGNORE, ierr) call MPI_FILE_CLOSE(thefile, ierr) call MPI_FINALIZE(ierr)

MPI_FILE_SET_VIEW(fh, disp, etype, filetype, datarep, info) [ INOUT fh] “pokrętło” pliku (handle) [ IN disp] przesunięcie (pozycja początkowego rekordu) (integer) [ IN etype] elementarny typ danych (handle) [ IN filetype] typ pliku (handle) [ IN datarep] reprezentacja danych (string) [ IN info] obiekt informacyjny (handle) C: int MPI_File_set_view(MPI_File fh, MPI_Offset disp, MPI_Datatype etype, MPI_Datatype filetype, char *datarep, MPI_Info info) FORTRAN/FORTRAN90 MPI_FILE_SET_VIEW(FH, DISP, ETYPE, FILETYPE, DATAREP, INFO, IERROR) INTEGER FH, ETYPE, FILETYPE, INFO, IERROR CHARACTER*(*) DATAREP INTEGER(KIND=MPI_OFFSET_KIND) DISP C++ void MPI::File::Set_view(MPI::Offset disp, const MPI::Datatype& etype, const MPI::Datatype& filetype, const char* datarep, const MPI::Info& info)

Czytanie pliku przez inną liczbę procesorów niż użyta to jego zapisu MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &myrank); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_File_open(MPI_COMM_WORLD, "testfile", MPI_MODE_RDONLY, MPI_INFO_NULL, &thefile); MPI_File_get_size(thefile, &filesize); /* in bytes */ filesize = filesize / sizeof(int); /* in number of ints */ bufsize = filesize / numprocs + 1; /* local number to read */ buf = (int *) malloc (bufsize * sizeof(int)); MPI_File_set_view(thefile, myrank * bufsize * sizeof(int), MPI_INT, MPI_INT, "native", MPI_INFO_NULL); MPI_File_read(thefile, buf, bufsize, MPI_INT, &status); MPI_Get_count(&status, MPI_INT, &count); printf("process %d read %d ints\n", myrank, count); MPI_File_close(&thefile); MPI_Finalize();

MPI_FILE_GET_SIZE(fh, size) [IN fhfile] “pokrętło” pliku (handle) [OUT size] rozmiar pliku w bajtach (integer) C: int MPI_File_get_size(MPI_File fh, MPI_Offset *size) FORTRAN/FORTRAN90: MPI_FILE_GET_SIZE(FH, SIZE, IERROR) INTEGER FH, IERROR INTEGER(KIND=MPI_OFFSET_KIND) SIZE C++ MPI::Offset MPI::File::Get_size() const

MPI_FILE_READ(fh, buf, count, datatype, status) [INOUT fh] “pokrętło” pliku (handle) [OUT buf] początkowy adres buforu (choice) [IN count] liczba elementów buforu (integer) IN datatype datatype of each buffer element (handle) [OUT status] obiekt stanu (Status) C: int MPI_File_read(MPI_File fh, void *buf, int count, MPI_Datatype datatype, MPI_Status *status) FORTRAN/FORTRAN90: MPI_FILE_READ(FH, BUF, COUNT, DATATYPE, STATUS, IERROR) BUF(*) INTEGER FH, COUNT, DATATYPE, STATUS(MPI_STATUS_SIZE), IERROR C++: void MPI::File::Read(void* buf, int count, const MPI::Datatype& datatype, MPI::Status& status) void MPI::File::Read(void* buf, int count, const MPI::Datatype& datatype)

Wydruk z programu piszącego bufor (dla BUFSIZE=2 i 4 procesorów)programu piszącego bufor mpirun -np 4./io3p | sort -n -k 1 Processor 0 buf[0]=0 Processor 0 buf[1]=1 Processor 1 buf[0]=2 Processor 1 buf[1]=3 Processor 2 buf[0]=4 Processor 2 buf[1]=5 Processor 3 buf[0]=6 Processor 3 buf[1]=7 Wydruk z programu czytającego bufor (dla 2 procesorów)programu czytającego bufor mpirun -np 2./io35p | sort -n -k 1 process 0 read 5 ints process 1 read 3 ints processor 0 buf[0]=0 processor 0 buf[1]=1 processor 0 buf[2]=2 processor 0 buf[3]=3 processor 0 buf[4]=4 processor 1 buf[0]=5 processor 1 buf[1]=6 processor 1 buf[2]=7

Inne sposoby pisania do pliku wspóldzielonego MPI_File_seek MPI_File_read_at MPI_File_write_at MPI_File_read_shared MPI_File_write_shared Wszystkie te operacje są operacjami komunikacji zbiorowej

Niewstrzymujące instrukcje czytania/pisania Standardowe operacje read i write są operacjami wstrzymującymi jak standardowe send i receive ale można użyć MPI_File_iread MPI_File_iwrite Żeby upewnić się, że pliki zostały zapisane/przeczytane należy dodać w odpowiednim miejscu instrukcję MPI_Wait tak jak w przypadku niewstrzymującego send lub receive.

Zbiorowe instrukcje czytania/pisania Odpowiednikami operacji komunikacji zbiorowej są MPI_File_read_all MPI_File_write_all Pierwszą operacją można porównać do broadcast a drugą do gather.

Operacje na pamięci odległej

Okno dostępu do pamięci: część pamięci adresowej danego procesora udostępnionej dla innych procesorów będących w danym komunikatorze. Utworzenie okna dostępu do pamięci jest operacją komunikacji zbiorowej. Okna dostępu do pamięci tworzą rozproszony obiekt złożony z częśći pamięci procesorów dostępnych dla innych. W obrębie okna są dostępne operacje: –get : uzyskiwanie danych z okna pamięci, –put : umieszczanie danych w oknie pamięci, –accumulate : modyfikacja danych w oknie dostępu do pamięci (np. dodawanie nowego składnika do sumy). Te operacje są niewstrzymujące i wymagają synchronizacji ( fence ).

get put Lokalna przestrzeń adresowa Okna dostępu do pamięci odległej Ilustracja operacji na pamięci odległej Procesor 0Procesor 1

Dla ilustracji rozważymy jeszcze raz obliczanie liczby  przez całkowanie numeryczne pochodnej funkcji arcus tangens metodą trapezów. Ilustracja przybliżonego obliczania liczby  przez całkowanie numeryczne dla liczby przedziałów n=10.

Zrównoleglenie algorytmu 1.Przedział całkowania dzieli się na n części: 1, 2,..., n 2.W układzie m procesorów, procesor 1 sumuje wkłady dla części 1, m+1, procesor 2 dla 2, m+2itd. 3.Procesory przesyłają swoje obliczone cząstkowe sumy do mastera, który oblicza sumę całkowitą. Źródło programu z użyciem MPI-1 (operacje broadcast i reduce) (C) Źrodło programu z użyciem MPI-2 (operacje na pamięci odległej) (C)

MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&n umprocs); MPI_Comm_rank(MPI_COMM_WORLD,& myid); MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&n umprocs); MPI_Comm_rank(MPI_COMM_WORLD,& myid); if (myid == 0) { MPI_Win_create(&n, sizeof(int), 1, MPI_INFO_NULL,MPI_COMM_WORLD, &nwin); MPI_Win_create(&pi, sizeof(double), 1, MPI_INFO_NULL,MPI_COMM_WORLD, &piwin); } else { MPI_Win_create(MPI_BOTTOM, 0, 1, MPI_INFO_NULL,MPI_COMM_WORLD, &nwin); MPI_Win_create(MPI_BOTTOM, 0, 1, MPI_INFO_NULL,MPI_COMM_WORLD, &piwin); } Porównanie kodu w MPI-1 (po lewej) z kodem w MPI-2 (po prawej)

while (!done) { if (myid == 0) { printf("Enter the number of intervals: (0 quits) "); scanf("%d",&n); } MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); if (n == 0) break; h = 1.0 / (double) n; sum = 0.0; for (i = myid + 1; i <= n; i += numprocs) { x = h * ((double)i - 0.5); sum += 4.0 / (1.0 + x*x); } mypi = h * sum; while (1) { if (myid == 0) { printf("Enter the number of intervals: (0 quits) "); scanf("%d",&n); pi = 0.0; } MPI_Win_fence(0, nwin); if (myid != 0) MPI_Get(&n, 1, MPI_INT, 0, 0, 1, MPI_INT, nwin); MPI_Win_fence(0, nwin); if (n == 0) break; else { h = 1.0 / (double) n; sum = 0.0; for (i = myid + 1; i <= n; i += numprocs) { x = h * ((double)i - 0.5); sum += (4.0 / (1.0 + x*x)); } mypi = h * sum;

MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); if (myid == 0) printf("pi is approximately %.16f, Error is %.16f\n", pi, fabs(pi - PI25DT)); } MPI_Finalize(); MPI_Win_fence( 0, piwin); MPI_Accumulate(&mypi, 1, MPI_DOUBLE, 0, 0, 1, MPI_DOUBLE, MPI_SUM, piwin); MPI_Win_fence(0, piwin); if (myid == 0) printf("pi is approximately %.16f, Error is %.16f\n", pi, fabs(pi - PI25DT)); } MPI_Win_free(&nwin); MPI_Win_free(&piwin); MPI_Finalize();

MPI_WIN_CREATE(base, size, disp_unit, info, comm, win) [IN base] początkowy adres okna (choice) [IN size] rozmiar okna w bajtach (integer, nieujemny) [IN disp_unit] lokalna jednostka przesunięcia w bajtach (integer, dodatni) [IN info] “pokrętło” obiektu informacyjnego (handle) [IN comm] komunikator (handle) [OUT win] “pokrętło” do okna (handle) C: int MPI_Win_create(void *base, MPI_Aint size, int disp_unit, MPI_Info info, MPI_Comm comm, MPI_Win *win) FORTRAN/FORTRAN90: MPI_WIN_CREATE(BASE, SIZE, DISP_UNIT, INFO, COMM, WIN, IERROR) BASE(*) INTEGER(KIND=MPI_ADDRESS_KIND) SIZE INTEGER DISP_UNIT, INFO, COMM, WIN, IERROR C++: static MPI::Win MPI::Win::Create(const void* base, MPI::Aint size, int disp_unit, const MPI::Info& info, const MPI::Intracomm& comm)

MPI_GET(origin_addr, origin_count, origin_datatype, target_rank, target_disp, target_count, target_datatype, win) [OUT origin_addr] początkowy adres początkowego bufora (choice) [IN origin_count] liczba elementów początkowego bufora (integer, nieujemny) [IN origin_datatype] typ danych każdego elementu (handle) [IN target_rank] rząd procesora celowego (integer, nieujemny) [IN target_disp] przesunięcie okna w stosunku do bufora celowego (integer, nieujemny) [IN target_count] liczba elementów bufora celowego (integer, nieujemny) [IN target_datatype] typ danych poszczególnych elementów bufora celowego (handle) [IN win] obiekt okna używany w komunikacji (handle)

C: int MPI_Get(void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Win win) FORTRAN/FORTRAN90 MPI_GET(ORIGIN_ADDR, ORIGIN_COUNT, ORIGIN_DATATYPE, TARGET_RANK, TARGET_DISP, TARGET_COUNT, TARGET_DATATYPE, WIN, IERROR) ORIGIN_ADDR(*) INTEGER(KIND=MPI_ADDRESS_KIND) TARGET_DISP INTEGER ORIGIN_COUNT, ORIGIN_DATATYPE, TARGET_RANK, TARGET_COUNT, TARGET_DATATYPE, WIN, IERROR C++: void MPI::Win::Get(const void *origin_addr, int origin_count, const MPI::Datatype& origin_datatype, int target_rank, MPI::Aint target_disp, int target_count, const MPI::Datatype& target_datatype) const

MPI_WIN_FENCE(assert, win) [IN assert] asercja programowa (integer) [IN win] obiekt okna (handle) C: int MPI_Win_fence(int assert, MPI_Win win) FORTRAN/FORTRAN90: MPI_WIN_FENCE(ASSERT, WIN, IERROR) INTEGER ASSERT, WIN, IERROR C++: void MPI::Win::Fence(int assert) const

MPI_WIN_FREE(win) [INOUT win] obiekt okna (handle) C: int MPI_Win_free(MPI_Win *win) FORTRAN/FORTRAN90: MPI_WIN_FREE(WIN, IERROR) INTEGER WIN, IERROR C++: void MPI::Win::Free()