Zadanie 1 - Macierze OMP
Transkrypt
Zadanie 1 - Macierze OMP
Zofia Sobocińska 19/11/2013 Zadanie 1 - Macierze OMP Mnożenie i dodawanie dwóch macierzy kwadratowych Programy z zadania pierwego mają dwa zadania: mnożenie i dodawanie dwóch macierzy: AN xN iBN xN . W celu uzyskania równoległości należało dopisać dyrektywę preprocesora wymaganą do działania OpenMP, przykładowo dla mnożenia macierzy: 1 2 3 4 5 6 7 8 #pragma omp p a r a l l e l f o r f o r ( s i z e t i = 0 ; i < s i z e ; i ++) f o r ( s i z e t j = 0 ; j < s i z e ; j ++) { C[ i ] [ j ] = 0 ; f o r ( s i z e t k = 0 ; k < s i z e ; k++) C [ i ] [ j ] += A[ i ] [ k ] ∗ B [ j ] [ k ] ; } } Początkowo macierze przechowywane były w tablicy jednowymiarowej (wiersz za wierszem), jednak krótkie czasy operacji dodawania (przy wymaganym czasie poniżej 2s) zmusiły do operowania na danych znacznie przekraczających maksymalny rozmiar tablicy jednowymiarowej. Zarówno dodawanie, jak i mnożenie macierzy, opierają się na najprostszych algorytmach: w mnożeniu dla każdej komórki każdego wiersza cm,n liczona jest suma iloczynów odpowiednich komórek macierzy P wejściowych A i B: cm,n = N i=1 am,i · bi,n . Sumowanie następuje w pętli. Dla dodawania iterujemy po każdej komórce każdego wiersza cm,n i przypisujemy mu sumę koRysunek 1: Zależność czasu obliczeń od liczby mórek macierzy A i B o tych samych inwątków - mnożenie macierzy deksach: cm,n = am,n + bm,n . Program został uruchomiony na maszynie 4-rdzeniowej z Hyper-Threadingiem w 11-tu konfiguracjach - po 5 razy dla liczby wątków 1-10 i 5 razy dla liczby wątków automatycznie przyjętej przez OpenMP. (standardowo jest to liczba rdzeni) Zmierzony został średni czas obliczeń w każdej z tych konfiguracji. Sumowanie jest wprawdzie znacznie mniej czasochłonne (dla dodawania Rysunek 2: Zależność czasu obliczeń od liczby wątków - dodawanie macierzy CN,N = AN xN + BN xN składa się na nie N × N operacji sumowania; dla porównania, mnożenie macierzy wymaga dla każdej komórki (N × N komórek) N operacji dodawania i N operacji mnożenia). Dla odpowiednio dużych danych obserwujemy jednak wyraźne przyśpieszenie. Równocześnie nie występuje tam problem zależności danych ani sterowania, problem daje się zatem łatwo zrównoleglić z uniknięciem narzutu związanego z synchronizacją wątków. 1 Sterowanie zachowaniem OpenMP Dyrektywa: 1 #pragma omp p a r a l l e l f o r d e f a u l t ( s h a r e d ) ma zachowanie zgodne z domyślnym. Wszystkie zmienne (za wyjątkiem prywatnych iteratorów pętli) uznawane są za dzielone. W poniższej postaci 1 #pragma omp p a r a l l e l f o r d e f a u l t ( none ) s h a r e d (A, B, C) f i r s t p r i v a t e ( r o z m i a r ) private ( i , j ) własnoręcznie wskazujemy zachowanie OpenMP w stosunku do określonych zmiennych. Możemy bez obaw dzielic zmienne wskaźników na macierze, ponieważ zawartości A i B nie modyfikujemy, natomiast w tablicy C każdy wątek modyfikuje odrębne komórki - nie ma obawy, że jeden z wątków nadpisze wynik pracy innego. Firstprivate wskazuje nam, że zmienna rozmiar ma zasięg prywatny dla każdego wątku, ale inicjalizowana jest wartością zmiennej rozmiar z wątku głównego. Istotne przy mierzeniu czasu wykonania było uniknięcie funkcji clock() - zwraca liczy ona bowiem liczę taktów CPU, a w sytuacji obliczeń wielowątkowych sumaryczny czas tych taktów będzie nie mniejszy niż przy jednowątkowych obliczeniach. Dodatkowo pojawi się narzut czasowy związany ze zrównolegleniem i pozorny wynik będzie wprost przeciwny do oczekiwanego. Wśród zalet zrównoleglenia z wykorzystaniem technologii OpenMP możemy wymienić: • Prostotę użycia - implementacja programów opartych na OpenMP nie wymaga specjalistycznej wiedzy, • Znaczne przyśpieszenie czasu obliczeń (co widać na wykresie), • Możliwość wprowadzenia własnych modyfikacji do strategii zrównoleglenia. Podsumowanie Środowisko uruchomieniowe oddało aplikacji do dyspozycji 4 rdzenie w technologii Hyper-Threading. Czas wykonywania się mnożenia macierzy wciąż spadał gdy wykorzystane zostały wszystkie CPU - fizyczne i wirtualne, a więc zysk przyniosło również współbieżne wykonanie się wątków. Czas wykonywania się dodawania macierzy spada mniej stabilnie. Wprawdzie Rysunek 3: Wykres przyśpieszenia (przykład dla mnożenia macierzy) na każdą operację arytmetyczną przypada kilka odniesień do pamięci, nie występują tu jednak zależności danych, dzięki czemu program ładnie się zrównolegla. Własnoręczne wskazywanie liczby wątków jest jednak w większości przypadków zbyteczne, ponieważ automatycznie dobrana ich liczba (zazwyczaj równa liczbie rdzeni) okazuje się najbardziej optymalna. 2