Skocz do: nawigacji, wyszukiwania

MICLAB:OpenMP


Środowisko i modele programowania

dr inż. Łukasz Szustak, Politechnika Częstochowska, IITiS
mgr inż. Kamil Halbiniak, Politechnika Częstochowska, IITiS



Standard OpenMP


OpenMP (Open Multi-Processing) jest wieloplatformowym standardem programowania równoległego zgodnym z modelem programowania równoległego z pamięcią wspólną. Ze względu na swoje właściwości, standard ten jest popularnie stosowany w obliczeniach wysokiej skali. OpenMP umożliwia implementację wielowątkowych aplikacji dedykowanych zarówno dla systemów Linux jak i Windows w językach programowania takich jak C, C++ oraz Fortran. Standard składa się z zestawu dyrektyw kompilatora, funkcji bibliotecznych oraz zmiennych środowiskowych, które mają wpływ na sposób wykonywania programu.


Każdy program zrównoleglony przy pomocy standardu OpenMP posiada wątek główny działający w obrębie całego programu. Aplikacja wykonywana jest w sposób sekwencyjny, aż do momentu napotkania obszaru równoległego, wewnątrz którego wszystkie uruchomione wątki współbieżnie wykonują przydzielone im zadania. Liczba regionów równoległych zdefiniowanych w aplikacji może być dowolna, a każdy z nich może zostać wykonany przy użyciu innej liczby wątków, których obciążenia mogą być zróżnicowane. Zadania zdefiniowane pomiędzy obszarami równoległymi realizowane są przez wątek główny. Na Rysunku 1 przedstawiono koncepcję zrównoleglenia aplikacji w standardzie OpenMP zgodną z modelem fork-join.


Fj model.png
Rysunek 1. Koncepcja zrównoleglenia w standardzie OpenMP


Do zrównoleglenia aplikacji w standardzie OpenMP wykorzystuje się dyrektywę #pragma omp parallel, która informuje kompilator, że poprzedzony nią obszar kodu źródłowego zostanie wykonany w sposób równoległy. Kompilacja kodu źródłowego zawierającego dyrektywy OpenMP wymaga ustawienia odpowiedniej flagi kompilatora, w przeciwnym razie zostaną one zignorowane a otrzymana aplikacja będzie aplikacją jednowątkową. Przykład kodu źródłowego zrównoleglonego przy użyciu standardu OpenMP zaprezentowano poniżej.


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

int main()
{ 
   #pragma omp parallel
   {
      printf("Hello World! Watek: %d\n", omp_get_thread_num());
   }
    
   return 0;
}
Listing 1. Zrównoleglenie w standardzie OpenMP


Jedną z podstawowych technik umożliwiających wykorzystanie wątków jest zrównoleglenie pętli. Do tego celu wykorzystuje się dyrektywę #pragma omp for informującą kompilator, że zrównoleglona zostanie pętla for. Każdy z wątków otrzymuje własny licznik iteracji, którego wartość wyznaczana jest przez środowisko wykonawcze OpenMP na podstawie liczby uruchomionych wątków. Przykładowo jeśli pętla liczy 50 iteracji i mają one zostać rozdzielone pomiędzy 5 wątków, każdy z wątków wykona 10 iteracji. Wątki OpenMP posiadają zmienne prywatne oraz publiczne. Dostęp do zmiennej prywatnej ma jedynie jeden określony wątek, natomiast do zmiennych publicznych (wspólnych) dostęp mają wszystkie uruchomione w danym momencie wątki. Przykładem zmiennej prywatnej jest przykładowo wewnętrzny licznik iteracji, który posiada każdy wątek. Zmiennymi publicznymi są na przykład całkowita liczba iteracji pętli lub zmienne wykorzystywane do wykonania obliczeń. Dodatkowo OpenMP daje programistom możliwość określenia własnego sposobu podziału iteracji.


Oprócz mechanizmu umożliwiającego zrównoleglenia pętli OpenMP oferuje szeroką gammę różnych konstrukcji umożliwiających równoległe przetwarzanie danych. Zalicza się do nich między innymi sekcje równoległe wykorzystywane do przydzielania wątkom wybranych fragmentów kodu, mechanizmy synchronizacji wątków oraz konstrukcję task, która pojawiła się w OpenMP 3.0. Konstrukcja ta pozwala na tworzenie zadań wykonywanych w obrębie pojedynczego wątku. Trzecia wersja standardu rozszerza wsparcie dla zagnieżdżonego zrównoleglenia, które daje możliwość definiowania liczby wątków wewnątrz obszaru równoległego. Istotną zmianą związaną z równoważeniem obciażeń, jest pojawienie się nowego dyspozytora pętli - schedule(auto). Dyspozytor ten automatycznie określa najlepszy sposób podziału iteracji pomiędzy wątki programu [2]. Równie istotną nowością, która pojawił się w trzeciej wersji standardu jest klauzula collapse. Pozwala ona przekształcić kilka zagnieżdzonych pętli w pojedynczą pętle. Zmianie uległa również lista procedur środowiska wykonawczego oraz lista zmiennych środowiskowych. OpenMP 3.0 pozwala na definiowanie własnego dyspozytora pętli.


Najnowsza - czwarta - wersja standardu OpenMP wydana została w 2013 roku. Oferuje ona szerokie wsparcie dla akceleratorów bazujących na architekturach masywnie wielordzeniowych typu GPU czy Intel MIC. Nowa konstrukcja - target - umożliwia przenoszenie obliczeń oraz danych na inne urządzenia obliczeniowe. Nową wersję standardu cechuje również możliwość tworzenia grup wątków (konstrukcja teams). W każdej z nowo utworzonych grup jeden wątek jest wątkiem głównym. Równie istotną nowością jest dyrektywa SIMD, która pozwala na wykonanie obliczeń wewnątrz pętli z użyciem instrukcji wektorowych. Czwarta wersja standardu wprowadza również możliwość grupowania zadań oraz ustawienia zależności między nimi. Istotną zmianą w porównaniu z poprzednimi wersjami stanadardu jest również pojawienie się mechanizmu pozwalającego określić sposób przypisane wątków do dostępnych rdzeni.



< Symetryczny model programowania

Standardy programowania równoległego - C++ 11 Threads >