1 / 32

Współczynnik przyspieszenia

Współczynnik przyspieszenia. n - wielkość zadania p - liczba procesorów T(n,p) – czas wykonania. Prawo Amdahla. b( n) – udział części sekwencyjnej. Sprawność programu równoległego. w(n) – ilość operacji związanych z wykonywaniem obliczeń h(n,p) – narzuty na komunikacje.

vera
Télécharger la présentation

Współczynnik przyspieszenia

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Współczynnik przyspieszenia n - wielkość zadania p - liczba procesorów T(n,p) – czas wykonania

  2. Prawo Amdahla b(n) – udział części sekwencyjnej

  3. Sprawność programu równoległego w(n) – ilość operacji związanych z wykonywaniem obliczeń h(n,p) – narzuty na komunikacje

  4. Oprogramowanie do obliczeń równoległych • System operacyjny • Języki wysokiego poziomu • Kompilatory • Biblioteki procedur numerycznych • Biblioteki do sterowania zadaniami • Narzędzia do wspomagania programowania, uruchamiania i profilowania

  5. Paradygmaty programowania równoległego • Możliwe rzadkie używanie bariery • Minimalizacja czasu zajmowanego przez mechanizmy synchronizacji (pamięć wspólna) • Minimalizacja czasu zajmowanego przez mechanizmy komunikacji (pamięć rozproszona)

  6. Stopień ziarnistości obliczeń równoległych • Ziarnistość opisuje ilość operacji obliczeniowych między punktami synchronizacji • Ilość danych przypadająca na procesor, częstotliwość komunikacji i synchronizacji • Grube ziarno, ang. coarse grain • Drobne ziarno, ang. fine grain

  7. Maszyny z pamięcią wspólną • Procesy • Mechanizmy komunikacji międzyprocesowej (IPC) • Mechanizm wątków (thread) • Tworzenie, niszczenie, identyfikacja, punkty synchronizacji (zamek, semafor) • Lokalne zmienne wątku • Dyrektywy kompilatora • Standard OpenMP

  8. SUBROUTINE MULKJI(A,B,C,N) C C Multiply A=B*C using index order K/J/I C DIMENSION A(N,N),B(N,N),C(N,N) C TIME3=TIMEF() CALL SECOND(TIME1) CMIC$ DO ALL SHARED(N, A, B, C) PRIVATE(K, J, I) DO 30 K=1,N DO 20 J=1,N CDIR$ IVDEP DO 10 I=1,N A(I,K)=A(I,K)+B(I,J)*C(J,K) 10 CONTINUE 20 CONTINUE 30 CONTINUE CALL SECOND(TIME2) TIME4=TIMEF() TEMP=(TIME4-TIME3)/1000.0 WRITE(*,’(1X,A,I5,A,G14.6,A,G14.6)’) *'MULIJK - N=',N,' CPU=',TIME2-TIME1,' Elapsed=',TEMP RETURN END

  9. Maszyny z pamięcią lokalną • High Performance Fortran (HPF) język dyrektyw zrównoleglających (data parallelism) • Linda: globalna baza danych (tuple space) out,eval,in,inp,rd,rdp • Parallel Virtual Machine (PVM) • Message Passing Interface (MPI)

  10. PROGRAM main IMPLICIT NONE INTEGER N PARAMETER (N=1000) INTEGER i, procnum(N), procsum(N), sum1, sum2 !HPF$ DISTRIBUTE PROCNUM(BLOCK) !HPF$ ALIGN PROCSUM(I) WITH PROCNUM(I) FORALL (i = 1:N) procnum(i) = i sum1 = SUM(procnum) PRINT *, 'Sum using global reduction is ', sum1 procsum = 0 DO i = 1, N procnum = CSHIFT(procnum,1) procsum = procsum + procnum END DO sum2 = procsum(1) PRINT *, 'Sum using local shifts is ', sum2 FORALL (i = 1:N) procnum(i) = procsum(i) - procsum(1) END FORALL IF (SUM(procnum) .EQ. 0) THEN PRINT *, 'Array values are the same.' ELSE PRINT *, 'OOPS! Array values are not the same!' ENDIF STOP END

  11. PVM • 1989 Oak Ridge National Laboratory • Komputery połączone siecią tworzą równoległą maszynę wirtualną • Biblioteka procedur i funkcji do tworzenia procesów użytkownika oraz przesyłania komunikatów miedzy procesami

  12. MPI • 1993 spotkania producentów i użytkowników maszyn równoległych • Standard interfejsu do przesyłania komunikatów opracowany przez MPI Forum • MPI jest nadzbiorem funkcji oferowanych przez PVM • wszystkie procesy maja wspólny kod

  13. Charakterystyka standardowego interfejsu przesyłania wiadomości MPI: • Kod jest napisany w „zwyczajnym” języku programowania (Fortran 77, Fortran 90, C, C++); przesyłanie wiadomości jest realizowane poprzez wywołanie odpowiednich procedur lub funkcji. • Wszystkie zmienne są lokalne dla danego procesora; inny procesor może je uzyskać tylko poprzez wymianę wiadomości. • Zwykle każdy procesor realizuje ten sam program wykonywalny (Single Program Multiple Data; SPMD), jednak występuje podział na procesor (procesory) nadzorujące (master) oraz „robotników” (workers) lub „niewolników” (slaves); realizują one inne fragmenty kodu, niż master. • IF (ME == MASTER) THEN • CALL SUB_MASTER(parametry) • ELSE • CALL SUB_WORKER(parametry) • ENDIF • W celu umożliwienia realizacji innych części kodu przez dany procesor lub grupę procesorów, każdy procesor ma własny identyfikator (0, 1, ..., NPROC-1).

  14. Konstrukcja systemu przesyłania wiadomości

  15. Definicja i konstrukcja wiadomości Wiadomość: pakiet danych przemieszczających się między procesorami. Podobnie jak list czy faks, oprócz właściwych przesyłanych danych musi ona być opakowana w „kopertę” (zawierać nagłówek) umożliwiający jej dostarczenie do właściwego odbiorcy:

  16. Koperta musi zawierać następujące informacje dla systemu przesyłania wiadomości: • Procesor wysyłający • Lokalizacja źródła wiadomości • Typ przesyłanych danych • Długość przesyłanych danych • Procesor(y) odbierające • Lokalizacja odbiorcy wiadomości • Wielkość buforu odbiorcy

  17. Rodzaje przesyłania wiadomości • W zależności od zachowania nadawcy po wysłaniu wiadomości, przesyłanie dzielimy na: • Asynchroniczne (asynchronous send) - nadawca wysyła wiadomość i nie interesuje się jej dalszymi losami. Można to porównać do wysłania okolicznościowej kartki do dalszego znajomego. • Synchroniczne - (synchronous send) nadawca żąda potwierdzenia dotarcia wiadomości. • W zależności od dalszej jego akcji dalszy podział jest następujący: • Wstrzymujące (blocking send) - nadawca wstrzymuje dalszą akcję do czasu potwierdzenia dotarcia wiadomości (można to porównać z wysyłaniem faksu lub rozmową telefoniczną). W MPI ten tryb wysyłania wiadomości jest standardem. • Niewstrzymujące (nonblocking send) - nadawca po wysłaniu wiadomości może wykonywać coś innego, po czym sprawdza, czy wiadomość dotarła. Realizacja operacji „niewstrzymujących” jest kontynuowana po powrocie do programu wywołującego. Po każdej instrukcja przesyłania „niewstrzymującego” powinna następować odpowiadająca jej instrukcja oczekiwania na potwierdzenie odbioru wiadomości. Jeżeli instrukcja oczekiwania jest kolejną instrukcją po instrukcji wysłania, jest to równoważne przesyłaniu ``wstrzymującemu''

  18. Asynchroniczne wysyłanie wiadomości (nadawca jedynie wie, że wiadomość została wysłana)

  19. Synchroniczne przesyłanie wiadomości (nadawca otrzymuje potwierdzenie dotarcia wiadomości)

  20. „Niewstrzymujące” przesyłanie wiadomości ( nonblocking send)

  21. Komunikacja zbiorowa (kolektywna) W MPI podstawowym trybem komunikacji jest tryb międzypunktowy „od procesora do procesora”. Dla ułatwienia pisania złożonych programów równoległych, które wymagają zebrania danych od wszystkich procesorów, rozesłania danych przez „nadzorcę” do „robotników”, synchronizacji procesorów, itp. wprowadzono tryb komunikacji zbiorowej, realizowany przez odpowiednie procedury MPI. Trzy najczęściej spotykane sytuacje: synchronizacja, broadcast (rozesłanie danych) i redukcja (zgrupowanie danych) są zilustrowane na poniższych rysunkach. Bariera - synchronizacja procesów

  22. Broadcast - jeden procesor przesyła dane do pozostałych

  23. Redukcja - procesory przekazują dane do jednego, np. w celu ich zsumowania

  24. Kompilacja z użyciem bibliotek MPI • Najprościej: użyć odpowiedniego skryptu wywołującego kompilator z dołączaniem bibliotek MPI: • mpif77 - Fortran 77 • mpicc - C • mpiCC - C++ • Poniżej podany jest przykład linii polecenia dla kompilacji kodu źródłowego programu hello w Fortranie 77. • mpif77 -o hello hello.f • Makefile FC = /usr/bin/g77 INSTALL_DIR=/opt/scali FFLAGS = -c ${OPT} -I$(INSTALL_DIR)/include LIBS = -L$(INSTALL_DIR)/lib_pgi -L$(INSTALL_DIR)/lib -lmpi -lfmpi .SUFFIXES: .f .f.o: ${FC} ${FFLAGS} $*.f hello: hello.o ${FC} -o hello $(LIBS) hello.o

  25. Pisanie kodów żródłowych z użyciem MPI - inicjalizacja, zakończenie, informacje o przydzielonych procesorach. W każdym żródle muszą się znaleźć definicje zawarte w pliku mpi.h (C) lub mpif.h (Fortran); plik ten musi być zaspecyfikowany jako pierwszy plik include. Program musi zawsze zawierać instrukcję inicjalizacji MPI (MPI_Init) i zakończenia MPI (MPI_Finalize). Komunikacja między procesorami oraz inne funkcje MPI są realizowane poprzez wywołanie odpowiednich procedur. Ogólna postać wywołania procedur MPI jest następująca: C: ierr = MPI_Xyyyyy( parametry ) lub MPI_Xyyyyy( parametry ) Zmienna ierr typu int jest kodem wyjścia z procedury; 0 oznacza zakończenie poprawne. Należy zwrócić uwagę, że nazwa procedury MPI zaczyna się od MPI_X, gdzie X jest pierwszą literą nazwy procedury (zawsze duża litera); dalsza część nazwy jest pisana małymi literami. Fortran (77 lub 90): CALL MPI_XYYYYY( parametry, IERROR ) Podobnie jak w wersji C, IERROR (zmienna typu INTEGER) jest kodem wyjścia. Zgodnie z konwencją Fortranu, wielkość liter w nazwie procedury nie odgrywa roli.

  26. Przykład programu z użyciem bibliotek MPI (C): #include "mpi.h" #include <stdio.h> int main( argc, argv ) int argc; char **argv; { int rank, size; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); printf( "Hello world! I'm %d of %d\n",rank, size ); MPI_Finalize(); return 0; }

  27. Przykład programu z użyciem bibliotek MPI (Fortran 77): program main include "mpif.h" integer rank, size call MPI_Init( ierr ) call MPI_Comm_rank( MPI_COMM_WORLD, rank, ierr ) call MPI_Comm_size( MPI_COMM_WORLD, size, ierr ) print 10, rank, size call MPI_Finalize(ierr); 10 format("Hello world! I'm",i3," of",i3) return end

  28. program main include 'mpif.h' integer rank, size, to, from, tag, count, i, ierr integer src, dest integer st_source, st_tag, st_count integer status(MPI_STATUS_SIZE) double precision data(100) call MPI_INIT( ierr ) call MPI_COMM_RANK( MPI_COMM_WORLD, rank, ierr ) call MPI_COMM_SIZE( MPI_COMM_WORLD, size, ierr ) print *, 'Process ', rank, ' of ', size, ' is alive' dest = size - 1 src = 0 if (rank .eq. src) then to = dest count = 10 tag = 2001 do 10 i=1, 10 10 data(i) = i call MPI_SEND( data, count, MPI_DOUBLE_PRECISION, to, + tag, MPI_COMM_WORLD, ierr ) else if (rank .eq. dest) then tag = MPI_ANY_TAG count = 10 from = MPI_ANY_SOURCE call MPI_RECV( data, count, MPI_DOUBLE_PRECISION, from, + tag, MPI_COMM_WORLD, status, ierr ) print *, rank, ' received', (data(i),i=1,10) endif call MPI_FINALIZE( ierr ) end

  29. #include "mpi.h" #include <stdio.h> int main( argc, argv ) int argc; char **argv; { int rank, size, to, from, tag, count, i, ierr; int src, dest; int st_source, st_tag, st_count; MPI_Status status; double data[100]; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &rank ); MPI_Comm_size( MPI_COMM_WORLD, &size ); printf("Process %d of %d is alive\n",rank,size); dest = size - 1; src = 0; if (rank == src) { to = dest; count = 10; tag = 2001; for (i=0;i<10;i++) { data[i] = i+1; } MPI_Send( data, count, MPI_DOUBLE_PRECISION, to,tag, MPI_COMM_WORLD ); }else if (rank == dest) { tag = MPI_ANY_TAG; count = 10; from = MPI_ANY_SOURCE; MPI_Recv( data, count, MPI_DOUBLE_PRECISION, from,tag, MPI_COMM_WORLD, &status ); printf("%d received ",rank); for (i=0;i<10;i++) printf ("%10.5f",data[i]); printf("\n"); } MPI_Finalize(); return 0; }

More Related