OpenMP - OpenMP

OpenMP
Logo OpenMP
Pierwotny autor (autorzy) Rada Przeglądu Architektury OpenMP
Deweloper(zy) Rada Przeglądu Architektury OpenMP
Wersja stabilna
5.1 / 13.11.2020 ; 9 miesięcy temu ( 2020-11-13 )
System operacyjny Wieloplatformowy
Platforma Wieloplatformowy
Rodzaj Rozszerzenie do C , C++ i Fortran ; API
Licencja Różny
Strona internetowa openmp .org

OpenMP ( Open Multi-Processing ) to interfejs programowania aplikacji (API), który obsługuje wieloplatformowe programowanie wieloprocesowe z pamięcią współdzieloną w językach C , C++ i Fortran , na wielu platformach, architekturach zestawów instrukcji i systemach operacyjnych , w tym Solaris , AIX , HP-UX , Linux , macOS i Windows . Składa się z zestawu dyrektyw kompilatora , procedur bibliotecznych i zmiennych środowiskowych, które wpływają na zachowanie w czasie wykonywania.

OpenMP jest zarządzane przez konsorcjum technologii non-profit OpenMP Architecture Review Board (lub OpenMP ARB ), wspólnie definiowane przez szerokie grono wiodących producentów sprzętu i oprogramowania komputerowego, w tym Arm , AMD , IBM , Intel , Cray , HP , Fujitsu , Nvidia , NEC , Red Hat , Texas Instruments i Oracle Corporation .

OpenMP wykorzystuje przenośny , skalowalny model, który daje programistom prosty i elastyczny interfejs do tworzenia aplikacji równoległych dla platform od standardowego komputera stacjonarnego po superkomputer .

Aplikacja zbudowana na hybrydowym modelu programowania równoległego może działać w klastrze komputerów przy użyciu zarówno OpenMP, jak i interfejsu przekazywania komunikatów (MPI), tak że OpenMP jest używany do równoległości w węźle (wielordzeniowym), podczas gdy MPI jest używany do równoległości między węzłami . Podjęto również wysiłki, aby uruchomić OpenMP w programowych systemach z rozproszoną pamięcią współdzieloną , przetłumaczyć OpenMP na MPI i rozszerzyć OpenMP na systemy z pamięcią niewspółdzieloną.

Projekt

Ilustracja wielowątkowości, w której główny wątek rozwidla kilka wątków, które wykonują równolegle bloki kodu.

OpenMP jest realizacja wielowątkowość , sposób parallelizing przy czym podstawowy gwintu (ciąg instrukcji wykonywanych kolejno) widełki określonej liczby sub -threads i podziałów Systemowa zadań między nimi. Wątki są następnie uruchamiane współbieżnie , a środowisko wykonawcze przydziela wątki różnym procesorom.

Sekcja kodu, która ma działać równolegle, jest odpowiednio oznaczona za pomocą dyrektywy kompilatora, która spowoduje utworzenie wątków przed wykonaniem sekcji. Każdy wątek ma dołączony identyfikator , który można uzyskać za pomocą funkcji (o nazwie omp_get_thread_num()). Identyfikator wątku jest liczbą całkowitą, a wątek główny ma identyfikator 0 . Po wykonaniu kodu równoległego wątki łączą się z powrotem do wątku podstawowego, który kontynuuje pracę do końca programu.

Domyślnie każdy wątek wykonuje zrównoległą sekcję kodu niezależnie. Konstrukcje współdzielenia pracy mogą służyć do dzielenia zadania między wątki, tak aby każdy wątek wykonywał przydzieloną mu część kodu. Za pomocą OpenMP można w ten sposób osiągnąć zarówno równoległość zadań, jak i równoległość danych .

Środowisko wykonawcze przydziela wątki procesorom w zależności od użycia, obciążenia maszyny i innych czynników. Środowisko wykonawcze może przypisać liczbę wątków na podstawie zmiennych środowiskowych lub kod może to zrobić za pomocą funkcji. Funkcje OpenMP są zawarte w pliku nagłówkowym oznaczonym jako omp.h w C / C++ .

Historia

OpenMP Architecture Review Board (ARB) opublikowała swoje pierwsze specyfikacje API, OpenMP for Fortran 1.0, w październiku 1997 roku. W październiku następnego roku wydali standard C/C++. W 2000 roku pojawiła się wersja 2.0 specyfikacji Fortran, a wersja 2.0 specyfikacji C/C++ została wydana w 2002 roku. Wersja 2.5 to połączona specyfikacja C/C++/Fortran wydana w 2005 roku.

Do wersji 2.0 OpenMP określał przede wszystkim sposoby na zrównoleglenie bardzo regularnych pętli, które występują w programowaniu numerycznym zorientowanym na macierz , gdzie liczba iteracji pętli jest znana w momencie wejścia. Zostało to uznane za ograniczenie i do wdrożeń dodano różne równoległe rozszerzenia zadań. W 2005 roku powstała próba standaryzacji paralelizmu zadań, która opublikowała propozycję w 2007 roku, czerpiąc inspirację z funkcji paralelizmu zadań w Cilk , X10 i Chapel .

Wersja 3.0 została wydana w maju 2008 roku. Nowe funkcje w wersji 3.0 obejmują koncepcję zadań i konstrukcję zadania , co znacznie poszerza zakres OpenMP poza konstrukcje pętli równoległych, które stanowiły większość OpenMP 2.0.

Wersja 4.0 specyfikacji została wydana w lipcu 2013 roku. Dodaje lub ulepsza następujące funkcje: wsparcie dla akceleratorów ; atomy ; obsługa błędów; powinowactwo wątku ; rozszerzenia zadań; redukcja zdefiniowana przez użytkownika ; obsługa SIMD ; Wsparcie dla Fortrana 2003 .

Obecna wersja to 5.1, wydana w listopadzie 2020 r.

Zauważ, że nie wszystkie kompilatory (i systemy operacyjne) obsługują pełny zestaw funkcji dla najnowszych wersji.

Podstawowe elementy

Wykres konstrukcji OpenMP

Podstawowymi elementami OpenMP są konstrukcje służące do tworzenia wątków, dystrybucji obciążenia (współdzielenia pracy), zarządzania środowiskiem danych, synchronizacji wątków, procedur wykonawczych na poziomie użytkownika i zmiennych środowiskowych.

W C/C++ OpenMP używa #pragmas . Poniżej wymieniono pragmy specyficzne dla OpenMP.

Tworzenie wątku

Równolegle pragma omp służy do rozwidlenia dodatkowych wątków w celu równoległego wykonania pracy zawartej w konstrukcji. Oryginalny wątek zostanie oznaczony jako wątek główny z identyfikatorem wątku 0.

Przykład (program C): Wyświetl "Witaj świecie." przy użyciu wielu wątków.

#include <stdio.h>
#include <omp.h>

int main(void)
{
    #pragma omp parallel
    printf("Hello, world.\n");
    return 0;
}

Użyj flagi -fopenmp, aby skompilować za pomocą GCC:

$ gcc -fopenmp hello.c -o hello

Wyjście na komputerze z dwoma rdzeniami, a co za tym idzie dwoma wątkami:

Hello, world.
Hello, world.

Jednak dane wyjściowe mogą być również zniekształcone z powodu sytuacji wyścigu spowodowanej przez dwa wątki współdzielące standardowe wyjście .

Hello, wHello, woorld.
rld.

(To, czy printfjest bezpieczny wątkowo, zależy od implementacji. std::coutZ drugiej strony C++ jest zawsze bezpieczny wątkowo.)

Konstrukcje współdzielenia pracy

Służy do określania, jak przypisać niezależną pracę do jednego lub wszystkich wątków.

  • omp for lub omp do : używane do dzielenia iteracji pętli między wątki, zwane również konstrukcjami pętli.
  • sekcje : przypisywanie kolejnych, ale niezależnych bloków kodu do różnych wątków
  • single : określenie bloku kodu, który jest wykonywany tylko przez jeden wątek, na końcu zakładana jest bariera
  • master : podobny do single, ale blok kodu zostanie wykonany tylko przez główny wątek i na końcu nie będzie żadnej bariery.

Przykład: zainicjuj wartość dużej tablicy równolegle, używając każdego wątku do wykonania części pracy

int main(int argc, char **argv)
{
    int a[100000];

    #pragma omp parallel for
    for (int i = 0; i < 100000; i++) {
        a[i] = 2 * i;
    }

    return 0;
}

Ten przykład jest żenująco równoległy i zależy tylko od wartości i . Flaga OpenMP Parallel for nakazuje systemowi OpenMP podzielić to zadanie na wątki robocze. Każdy z wątków otrzyma unikalną i prywatną wersję zmiennej. Na przykład, z dwoma wątkami roboczymi , jeden wątek może otrzymać wersję i, która działa od 0 do 49999, podczas gdy drugi otrzyma wersję działającą od 50000 do 99999.

Dyrektywy wariantowe

Dyrektywy Variant to jedna z głównych funkcji wprowadzonych w specyfikacji OpenMP 5.0, aby ułatwić programistom poprawę przenośności wydajności. Umożliwiają adaptację prag OpenMP i kodu użytkownika w czasie kompilacji. Specyfikacja definiuje cechy opisujące aktywne konstrukcje OpenMP, urządzenia wykonawcze i funkcjonalność zapewnianą przez implementację, selektory kontekstu oparte na cechach i warunkach zdefiniowanych przez użytkownika oraz dyrektywy metadyrektywy i dyrektywy deklarowania dla użytkowników do programowania tego samego regionu kodu z dyrektywami wariantowymi.

  • Metadirective jest wykonywalny, że dyrektywa warunkowo postanawia innej dyrektywy w czasie kompilacji wybierając z wielokrotnym dyrektywy wariantów w oparciu o cechy, które definiują warunek OpenMP lub kontekstu.
  • Dyrektywa define variant ma podobną funkcjonalność jak metadyrektywa, ale wybiera wariant funkcji w witrynie wywołania na podstawie kontekstu lub warunków zdefiniowanych przez użytkownika.

Mechanizm zapewniany przez dwie dyrektywy wariantowe do wybierania wariantów jest wygodniejszy w użyciu niż wstępne przetwarzanie C/C++, ponieważ bezpośrednio obsługuje wybór wariantów w OpenMP i umożliwia kompilatorowi OpenMP analizę i określenie ostatecznej dyrektywy na podstawie wariantów i kontekstu.

// code adaptation using preprocessing directives

int v1[N], v2[N], v3[N];
#if defined(nvptx)     
 #pragma omp target teams distribute parallel loop map(to:v1,v2) map(from:v3)
  for (int i= 0; i< N; i++) 
     v3[i] = v1[i] * v2[i];  
#else 
 #pragma omp target parallel loop map(to:v1,v2) map(from:v3)
  for (int i= 0; i< N; i++) 
     v3[i] = v1[i] * v2[i];  
#endif


// code adaptation using metadirective in OpenMP 5.0

int v1[N], v2[N], v3[N];
#pragma omp target map(to:v1,v2) map(from:v3)
  #pragma omp metadirective \
     when(device={arch(nvptx)}: target teams distribute parallel loop)\
     default(target parallel loop)
  for (int i= 0; i< N; i++) 
     v3[i] = v1[i] * v2[i];

Klauzule

Ponieważ OpenMP jest modelem programowania pamięci współdzielonej, większość zmiennych w kodzie OpenMP jest domyślnie widoczna dla wszystkich wątków. Czasami jednak zmienne prywatne są niezbędne, aby uniknąć sytuacji wyścigu i istnieje potrzeba przekazywania wartości między sekwencyjną częścią a regionem równoległym (blok kodu wykonywany równolegle), więc zarządzanie środowiskiem danych jest wprowadzane jako klauzule atrybutów udostępniania danych poprzez dołączenie ich do dyrektywa OpenMP. Różne rodzaje klauzul to:

Klauzule atrybutów udostępniania danych
  • shared : dane zadeklarowane poza regionem równoległym są udostępniane, co oznacza, że ​​są widoczne i dostępne dla wszystkich wątków jednocześnie. Domyślnie wszystkie zmienne w regionie współdzielenia pracy są współużytkowane z wyjątkiem licznika iteracji pętli.
  • private : dane zadeklarowane w regionie równoległym są prywatne dla każdego wątku, co oznacza, że ​​każdy wątek będzie miał kopię lokalną i użyje jej jako zmiennej tymczasowej. Zmienna prywatna nie jest inicjowana, a jej wartość nie jest utrzymywana do użytku poza regionem równoległym. Domyślnie liczniki iteracji pętli w konstrukcjach pętli OpenMP są prywatne.
  • default : pozwala programiście stwierdzić, że domyślny zasięg danych w regionie równoległym będzie albo shared , albo none dla C/C++ lub shared , firstprivate , private lub none dla Fortranu. Opcja none zmusza programistę do deklarowania każdej zmiennej w regionie równoległym przy użyciu klauzul atrybutów udostępniania danych.
  • firstprivate : jak prywatny, z wyjątkiem zainicjowania do oryginalnej wartości.
  • lastprivate : jak private, z wyjątkiem tego, że oryginalna wartość jest aktualizowana po konstrukcji.
  • redukcja : bezpieczny sposób łączenia pracy ze wszystkich wątków po konstrukcji.
Klauzule synchronizacji
  • krytyczne : załączony blok kodu będzie wykonywany tylko przez jeden wątek na raz, a nie jednocześnie wykonywany przez wiele wątków. Jest często używany do ochrony udostępnianych danych przed warunkami wyścigu .
  • atomowe : aktualizacja pamięci (zapis lub odczyt-modyfikacja-zapis) w następnej instrukcji zostanie wykonana niepodzielnie. Nie sprawia, że ​​cała instrukcja staje się atomowa; tylko aktualizacja pamięci jest niepodzielna. Kompilator może użyć specjalnych instrukcji sprzętowych, aby uzyskać lepszą wydajność niż w przypadku korzystania z funkcji krytycznej .
  • uporządkowany : blok strukturalny jest wykonywany w kolejności, w jakiej iteracje byłyby wykonywane w pętli sekwencyjnej
  • bariera : każdy wątek czeka, aż wszystkie inne wątki zespołu osiągną ten punkt. Konstrukcja współdzielenia pracy ma na końcu niejawną synchronizację bariery.
  • nowait : określa, że ​​wątki kończące przydzieloną pracę mogą kontynuować bez czekania na zakończenie wszystkich wątków w zespole. W przypadku braku tej klauzuli wątki napotykają synchronizację bariery na końcu konstrukcji współdzielenia pracy.
Klauzule harmonogramowe
  • harmonogram (typ, porcja) : jest to przydatne, jeśli konstrukcja współdzielenia pracy to pętla do lub pętla for. Iteracje w konstrukcji współdzielenia pracy są przypisywane do wątków zgodnie z metodą planowania zdefiniowaną w tej klauzuli. Trzy rodzaje planowania to:
  1. static : tutaj wszystkie wątki są przydzielane iteracje przed wykonaniem iteracji pętli. Iteracje są domyślnie równo podzielone między wątki. Jednak określenie liczby całkowitej dla porcji parametru spowoduje przydzielenie liczby porcji ciągłych iteracji do określonego wątku.
  2. dynamic : W tym przypadku niektóre iteracje są przydzielane do mniejszej liczby wątków. Gdy określony wątek zakończy przydzieloną iterację, powraca, aby pobrać kolejny z pozostałych iteracji. Parametr chunk definiuje liczbę ciągłych iteracji, które są jednocześnie przydzielane do wątku.
  3. guide : Duża część ciągłych iteracji jest przydzielana dynamicznie do każdego wątku (jak powyżej). Rozmiar porcji zmniejsza się wykładniczo z każdym kolejnym przydziałem do minimalnego rozmiaru określonego w parametrze porcja
JEŻELI kontrola
  • if : spowoduje to, że wątki zrównoleglą zadanie tylko wtedy, gdy spełniony zostanie warunek. W przeciwnym razie blok kodu jest wykonywany szeregowo.
Inicjalizacja
  • firstprivate : dane są prywatne dla każdego wątku, ale są inicjowane przy użyciu wartości zmiennej o tej samej nazwie z głównego wątku.
  • lastprivate : dane są prywatne dla każdego wątku. Wartość tych prywatnych danych zostanie skopiowana do zmiennej globalnej o tej samej nazwie poza regionem równoległym, jeśli bieżąca iteracja jest ostatnią iteracją w zrównoleglonej pętli. Zmienna może być zarówno firstprivate i lastprivate .
  • threadprivate : dane są danymi globalnymi, ale są prywatne w każdym regionie równoległym w czasie wykonywania. Różnica między threadprivate a private to globalny zakres skojarzony z threadprivate i zachowaną wartością w równoległych regionach.
Kopiowanie danych
  • copyin : podobnie jak firstprivate dla zmiennych prywatnych, zmienne threadprivate nie są inicjowane, chyba że do przekazania wartości z odpowiednich zmiennych globalnych użyto copyin . Nie jest potrzebne kopiowanie , ponieważ wartość zmiennej threadprivate jest zachowywana podczas wykonywania całego programu.
  • copyprivate : używane z singlem do obsługi kopiowania wartości danych z prywatnych obiektów w jednym wątku ( pojedynczy wątek) do odpowiednich obiektów w innych wątkach w zespole.
Zmniejszenie
  • reduction (operator | intrinsic : list) : zmienna ma kopię lokalną w każdym wątku, ale wartości kopii lokalnych zostaną podsumowane (zredukowane) do globalnej zmiennej współdzielonej. Jest to bardzo przydatne, jeśli określona operacja (określona w operatorze dla tej konkretnej klauzuli) na zmiennej działa iteracyjnie, tak że jej wartość w określonej iteracji zależy od jej wartości w poprzedniej iteracji. Kroki prowadzące do przyrostu operacyjnego są równoległe, ale wątki aktualizują zmienną globalną w sposób bezpieczny dla wątków. Byłoby to wymagane przy zrównoleglaniu numerycznej integracji funkcji i równań różniczkowych , jako typowy przykład.
Inni
  • flush : Wartość tej zmiennej jest przywracana z rejestru do pamięci w celu użycia tej wartości poza częścią równoległą
  • master : Wykonywane tylko przez wątek główny (wątek, który rozwidlał wszystkie inne podczas wykonywania dyrektywy OpenMP). Brak ukrytej bariery; inni członkowie zespołu (wątki) niewymagane do osiągnięcia.

Procedury uruchomieniowe na poziomie użytkownika

Służy do modyfikowania/sprawdzania liczby wątków, wykrywania, czy kontekst wykonania znajduje się w regionie równoległym, liczby procesorów w bieżącym systemie, ustawiania/rozbrajania blokad, funkcji czasowych itp.

Zmienne środowiska

Metoda zmiany funkcji wykonawczych aplikacji OpenMP. Służy do kontrolowania planowania iteracji pętli, domyślnej liczby wątków itp. Na przykład OMP_NUM_THREADS służy do określania liczby wątków dla aplikacji.

Realizacje

OpenMP został zaimplementowany w wielu komercyjnych kompilatorach. Na przykład obsługują go Visual C++ 2005, 2008, 2010, 2012 i 2013 (OpenMP 2.0, w wersjach Professional, Team System, Premium i Ultimate), a także Intel Parallel Studio dla różnych procesorów. Kompilatory i narzędzia Oracle Solaris Studio obsługują najnowsze specyfikacje OpenMP z ulepszeniami produktywności dla platform Solaris OS (UltraSPARC i x86/x64) oraz Linux. Kompilatory Fortran, C i C++ z The Portland Group również obsługują OpenMP 2.5. GCC wspiera również OpenMP od wersji 4.2.

Kompilatory z implementacją OpenMP 3.0:

  • GCC 4.3.1
  • Kompilator Mercurium
  • Kompilatory Intel Fortran i C/C++ w wersji 11.0 i 11.1, Intel C/C++ i Fortran Composer XE 2011 oraz Intel Parallel Studio.
  • Kompilator IBM XL
  • Sun Studio 12 aktualizacja 1 ma pełną implementację OpenMP 3.0
  • Obliczenia wieloprocesorowe ( "MPC" .)

Kilka kompilatorów obsługuje OpenMP 3.1:

  • GCC 4.7
  • Kompilatory Intel Fortran i C/C++ 12.1
  • Kompilatory IBM XL C/C++ dla AIX i Linux, V13.1 i IBM XL Fortran dla AIX i Linux, V14.1
  • LLVM/Klang 3,7
  • Kompilatory Absoft Fortran v. 19 dla Windows, Mac OS X i Linux

Kompilatory wspierające OpenMP 4.0:

  • GCC 4.9.0 dla C/C++, GCC 4.9.1 dla Fortran
  • Kompilatory Intel Fortran i C/C++ 15,0
  • IBM XL C/C++ dla systemu Linux, V13.1 (częściowy) i XL Fortran dla systemu Linux, V15.1 (częściowy)
  • LLVM/Clang 3.7 (częściowo)

Kilka kompilatorów obsługujących OpenMP 4.5:

  • GCC 6 dla C/C++
  • Kompilatory Intel Fortran i C/C++ 17,0, 18,0, 19,0
  • LLVM/Klang 12

Częściowe wsparcie dla OpenMP 5.0:

  • GCC 9 dla C/C++
  • Kompilatory Intel Fortran i C/C++ 19,1
  • LLVM/Klang 12

Auto-parallelujące kompilatory, które generują kod źródłowy z adnotacjami dyrektyw OpenMP:

Kilka profilerów i debugerów wyraźnie obsługuje OpenMP:

  • Intel VTune Profiler - profilera dla x86 CPU i X e architektur GPU
  • Intel Advisor — narzędzie wspomagające projektowanie i analizujące kody OpenMP i MPI
  • Allinea Distributed Debugging Tool (DDT) – debugger dla kodów OpenMP i MPI
  • Allinea MAP – profiler dla kodów OpenMP i MPI
  • TotalView - debugger firmy Rogue Wave Software dla OpenMP, MPI i kodów szeregowych
  • ompP – profiler dla OpenMP
  • VAMPIR – profiler dla kodu OpenMP i MPI

Plusy i minusy

Plusy:

  • Przenośny kod wielowątkowości (w C/C++ i innych językach, aby uzyskać wielowątkowość, zazwyczaj trzeba wywoływać operacje podstawowe specyficzne dla platformy).
  • Proste: nie musisz zajmować się przekazywaniem wiadomości, tak jak robi to MPI .
  • Układ i rozkład danych są obsługiwane automatycznie przez dyrektywy.
  • Skalowalność porównywalna do MPI w systemach z pamięcią współdzieloną.
  • Równoległość przyrostowa: może pracować na jednej części programu w tym samym czasie, nie są potrzebne żadne radykalne zmiany w kodzie.
  • Ujednolicony kod dla aplikacji szeregowych i równoległych: konstrukcje OpenMP są traktowane jako komentarze, gdy używane są kompilatory sekwencyjne.
  • Instrukcje kodu oryginalnego (szeregowego) nie muszą być generalnie modyfikowane podczas zrównoleglenia z OpenMP. Zmniejsza to ryzyko nieumyślnego wprowadzenia błędów.
  • Zarówno gruboziarnistych i drobnoziarnistych są możliwe równoległość.
  • W nieregularnych aplikacjach wielofizycznych, które nie stosują się wyłącznie do trybu obliczeń SPMD , jak to ma miejsce w ściśle sprzężonych układach płyn-cząstki, elastyczność OpenMP może mieć dużą przewagę wydajności nad MPI .
  • Może być używany z różnymi akceleratorami, takimi jak GPGPU i FPGA .

Cons:

  • Ryzyko wprowadzenia trudnych do debugowania błędów synchronizacji i warunków wyścigu .
  • Od 2017 r. działa wydajnie tylko na platformach wieloprocesorowych z pamięcią współdzieloną (zobacz jednak Cluster OpenMP firmy Intel i inne platformy z rozproszoną pamięcią współdzieloną ).
  • Wymaga kompilatora obsługującego OpenMP.
  • Skalowalność jest ograniczona architekturą pamięci.
  • Brak obsługi funkcji porównania i zamiany .
  • Brak niezawodnej obsługi błędów.
  • Brakuje drobnoziarnistych mechanizmów kontroli mapowania procesora wątków.
  • Duża szansa na przypadkowe napisanie fałszywego kodu udostępniania .

Oczekiwania dotyczące wydajności

Można się spodziewać N- krotnego przyspieszenia podczas uruchamiania programu zrównoleglego przy użyciu OpenMP na platformie procesora N. Jednak rzadko zdarza się to z następujących powodów:

  • Gdy zależność istnieje, proces musi czekać na obliczenie danych, od których zależy.
  • Gdy wiele procesów współdzieli zasób nierównoległy (np. plik do zapisu), ich żądania są wykonywane sekwencyjnie. Dlatego każdy wątek musi czekać, aż drugi wątek zwolni zasób.
  • Duża część programu może nie być zrównoleglona przez OpenMP, co oznacza, że ​​teoretyczna górna granica przyspieszenia jest ograniczona zgodnie z prawem Amdahla .
  • N procesorów w symetrycznym przetwarzaniu wieloprocesorowym (SMP) może mieć N razy większą moc obliczeniową, ale przepustowość pamięci zwykle nie zwiększa się N razy. Dość często oryginalna ścieżka pamięci jest współużytkowana przez wiele procesorów i można zaobserwować pogorszenie wydajności, gdy rywalizują one o przepustowość pamięci współdzielonej.
  • Wiele innych typowych problemów wpływających na końcowe przyspieszenie obliczeń równoległych dotyczy również OpenMP, takich jak równoważenie obciążenia i narzut synchronizacji.
  • Optymalizacja kompilatora może nie być tak skuteczna podczas wywoływania OpenMP. Może to często prowadzić do tego, że jednowątkowy program OpenMP będzie działał wolniej niż ten sam kod skompilowany bez flagi OpenMP (który będzie w pełni szeregowy).

Powinowactwo wątku

Niektórzy dostawcy zalecają ustawienie koligacji procesora w wątkach OpenMP, aby powiązać je z konkretnymi rdzeniami procesora. Minimalizuje to migrację wątków i koszt przełączania kontekstu między rdzeniami. Poprawia również lokalizację danych i zmniejsza ruch związany ze spójnością pamięci podręcznej między rdzeniami (lub procesorami).

Benchmarki

Opracowano szereg testów porównawczych, aby zademonstrować użycie OpenMP, przetestować jego wydajność i ocenić poprawność.

Proste przykłady

Testy wydajności obejmują:

Wzorce poprawności obejmują:

Zobacz też

Bibliografia

Dalsza lektura

Zewnętrzne linki