Biuletyn nr 7

Biuletyn KDM
1 | 2 | 3 | 4 | 5
6 | 7 | 8 | 9 | 10
11 | 12 | 13 | 14
15 | 16 | 17 | 18
19 | 20 | 21 | 22
23 | 24 | 25 | 26
27 | 28 | 29 | 30
31 | 32
Lista biuletynów

Biuletyn nr 7 (16 grudnia 2005)

Spis treści

Porady: Autouzupełnianie w tcsh

Autor: Franek Rakowski


Rzeczą oczywistą jest, dla każdego użytkownika systemu Linux pracującego za konsolą, iż nic tak nie ułatwia pracy jak to, iż linia poleceń konsoli "domyśla się" co właśnie chcemy napisać. W standartowych dystrybucjach autouzupełnianie jest normą i wiadomo, że raczej musimy pamiętać pierwsze litery katalogów, plików czy komend, natomiast reszta zostanie nam podpowiedziana. Przyzwyczjeni do tego faktu, doświadczamy niemiłego zaskoczenia kiedy to system po wydaniu komendy lpr -Pg... i naciśnięciu tabulatora, niestety nie domyśla się jak nazywa się nasza drukarka!

No właśnie, jest tak dlatego, iż powłoka nie umie wszyskiego się domyśleć. Ale tu w sukurs przychodzi nam polecenie complete, które właśnie służy do uczenia powłoki kiedy i w jaki sposób domyślać się co chcemy napisać. Nie chcąc kopiować strony manuala dostępnej każdemu użytkownikowi Linuxa, zamierzam raczej opisać to niezwykle przydatne narzędzie i w sposób przyjazny wprowadzić czytelnika w tajniki jego użycia, raczej odpowiadając na pytanie "Jak można osiągnąć dany cel?", niż "Do czego konkretnie służą wszystkie opcje polecenia complete i jak są zdefiniowane?".

Wyszczególniłem kilka częstych, jak mi się wydaje, sytuacji w których chcemy aby polecenie complete zadziałało. ( choć, w dużej liczbie przypadków, funkcja autouzupełniania jest już ustawiana przy wywołaniu powłoki. )

  • uzupełnienie komendy, np. zaczynamy acro... i po naciśnięciu tabulatora się rozwija do acroread - takie uzupełnianie z reguły w powłoce jest już ustawione.
  • uzupełnianie argumentów komendy, np cp [i tu szuka plików w naszym katalogu do rozwinięcia ] - to też już jest. ale, acroread [i tu chcemy aby powłoka uzupełniała nazwy plików kończące się na .pdf lub .PDF ] - to trzeba będzie ustawić
  • uzupełnianie opcji komend, np. lpr [tu chcemy nauczyć powłokę zgadywać jakie mamy drukarki] - tego chyba nigdzie nie ma...

A więc do dzieła, składnia polecenia complete wygląda następująco:

complete [komenda [wyraz/wzorzec/lista[:wybór]/]]

komenda jest nazwą komendy lub jej wzorcem (glob-pattern), czyli np. convert lub co*

wyraz w to miejsce wstawiamy literkę, która mówi o tym który wyraz ma być "autouzupełniony", a są one takie:

c będzie uzupełniał wyraz aktualnie pisany, jeśli jego początek pasuje do wzorca. Uzupełniane jest wyrazami ze zbioru lista, który oczywiście można zdefiniować, ale o tym później.

C niby tak samo jak wyżej, ale ze zbioru lista weźmie tylko te wyrazy które pasują do wzorca.

Jak jest różniaca? Ano taka: wyobraźmy sobie, iż chcemy uzupełnić nazwy plików inkludowanych w czasie kompilacji: i piszemy: cc -I[i tu chcemy aby domyślał się nazw plików z naszego katalogu], ale one oczywiście nie zaczynają się od -I ! Czyli początek wyrazu nie może pasować do wyrazów z listy, ale polecenie complete musi wiedzieć że po -I coś ma uzupełniać. W drugim przypadku C, mamy np. acroread [i tu nazwa pliku], który jednakowoż musi pasować do tego co zaczeliśmy pisać, jak i do zawartości listy.

p rozpoznaje który wyraz ma uzupełnić po jego pozycji linii poleceń, która jest umieszczana w polu wzorzec, przy czym pierwszy wyraz (najczęściej komenda) ma wskaźnik 0,

n i N uzupełnia następny (lub drugi w kolejności) wyraz od tego, do którego pasuje wzorzec.

Zbiór lista możemy określić, również poprzez podanie literki. Tym razem oznaczenia są takie (najpotrzebniejsze):

a zbiór aliasów,

c komendy powłoki,

d katalogi,

e zmienne środowiskowe,

f pliki,

u użytkownicy,

i inne opisane w manualu. ( w man tcsh, opisane są dwie komendy complete, to ta druga.) Można też oczywiście zdefniować własną listę. Robi się to tak jak definiuje się zmienną łańcuchową w tcsh, czyli:

 set mojalista=(raz dwa trzy)

a w poleceniu complete odwołuje się do niej poprzez $mojalista.

Wzorzec zamieszcany w polu select, jest opcjonalny i służący do wybrania ze zbioru lista tylko tego co nas intresuje, np. ze zbioru wszyskich plików tylko te co pasują do wzorca *.ps

Na zakończenie podam kilka typowych i przydatnych przykładów użycia polecenia complete:

- chcemy aby po napisaniu lpr -P, powłoka uzupełniła nazwę drukarki z, powiedzmy, dwóch dostępnych: pierwszadrukarka i drugadrukarka.

definiujemy zmienną:

 set drukarki=(pierwszdrukarka drugadrukarka)

i używamy polecenia complete:

 complete lpr 'c/-P/$drukarki/'.

Już działa nam uzupełnianie nazw drukarek, ale chcemy jeszcze aby dalej odgadywał pliki postscriptowe ( *.ps).Modyfikujemy zatem komendę complete:

 complete lpr 'c/-P/$drukarki/' 'C/*/f:*.ps/',

można to zrobić w inny sposób:

 complete lpr 'c/-P/$drukarki/' 'p/*/f:*.ps/'.

Do uzupełniania opcji podobnych do siebie komend, np lpq i lprm można użyć wzorca:

 complete lp{q,rm} 'c/-P/$drukarki/'

i podobnie można używać wzorców w polu select:

 complete gv 'C/*/f:*.{ps,PS,pdf}/'

aby uzupełnione zostały nazwy plików, podane po komendzie gv, a kończące się na ps, PS, lub pdf.

Mam nadzieję, iż podany zbiór przykładów i wiadomości, przyspieszy i umili ciężką czasami pracę z systemem. Wiadomo bowiem, że po wielu godznach pracy, kiedy to na zakończenie chcemy wydrukować jakąś pracę i wziąć ją do domu, naprawdę ciężko sobie przypomnieć jak nazywają się nasze drukarki...

Narzędzia: Matlab

Autor: Maciej Szpindler

Wprowadzenie

MATLAB jest językiem wysokiego poziomu razem z całym środowiskiem użytkownika, służącym do obliczeń numerycznych, analizy i przetwarzania danych, wizualizacji oraz do wielu innych zastosowań. Pakiet MATLAB zawiera także wiele opcjonalnych rozszerzeń i bibliotek oferujących dodatkową funkcjonalność.

Środowisko MATLABa

MATLAB posiada graficzny interfejs użytkownika działający w trybie interaktywnym. Komendy można wprowadzać bezpośrednio z linii poleceń MATLABa, korzystać z ogromnej liczby funkcji bibliotecznych lub tworzyć własne funkcje i skrypty. Skrypty MATLABa mają postać tak zwanych m-plików, które są zwykłymi plikami tekstowymi zawierającymi instrukcje, funkcje zdefiniowane przez użytkownika lub odwołania do wbudowanych funcji MATLABa. Jednocześnie język programowania pakietu MATLAB jest pełnoprawnym językiem programowania wysokiego poziomu, umożliwia także pisanie programów zorientowanych obiektowo.

Praca z MATLABem

W MATLABie obowiązuje zasada, że każdy obiekt jest macierzą, stąd też nazwa MATLAB = MATrix LABoratory. Większość operacji można wykonywać blokowo, to znaczy wektorowo lub macierzowo. Ze względu na budowę MATLABa często skutkuje to znączacym wzrostem szybkości wykonywanych obliczeń. Pakiet zawiera bardzo dużą liczbę standardowych funkcji matematycznych, które również działają macierzowo. W MATLABie działa skrócona notacja dwukropkowa pętli, znana z np. Fortrana.

>> x = 0:0.1:10;
>> y = sin(1./(x(2:10)))

y =

  -0.5440   -0.9589   -0.1906    0.5985    0.9093    0.9954    0.9899    0.9490    0.8962

MATLAB posiada duże możliwości wizualizacji wyników obliczeń. Możliwe jest rysowanie najróżniejszych wykresów 2- i 3-wymiarowych, a także manipulacja obrazami cyfrowymi.

>> [X, Y] = meshgrid(-3:0.1:3, -3:0.1:3);
>> M = sin(X).^2 + cos(Y).^2;
>> mesh(X,Y,M)

Matlab1.png Rys.1. Wykres powierzchni.

>> contour(X,Y,M)

Matlab2.png Rys.2. Wykres poziomic.

>> plot(X(1,:), M(1,:), '.-', X(1,:), 0.9, '.-')

Matlab3.png Rys.3. Przekrój powierzchni.

MATLAB posiada rozbudowany system pomocy zawierający opisy wszystkich funkcji oraz dostępnych Toolbox-ów.

Przykładowy programik

Jako przykład rozwiążemy równanie Van der Pola. Jest to równanie różniczkowe zwyczajne drugiego rzędu, postaci:

\ddot{x} + \epsilon (x^2 - 1) \dot{x} + x = 0.

Do rozwiązania tego równania użyjemy solvera ode45, wbudowanej funkcji MATLABa. Funkcja ta potrafi rozwiązać równanie zwyczajne zadane w postaci:

\dot{x} = f(x(t), t),

sprowadzamy zatem równanie do układu dwóch równań pierwszego rzędu:

\dot{x_{1}} = x_{2}

\dot{x_{2}} = -\epsilon (\dot{x_{1}} -1) x_{2} - x_{1}.

Potrzebujemy jeszcze określić wartości początkowe dla równania x(t_{0}) = x_{0}, oraz przedział czasowy t \in [t_{0}, t_{1}] na którym szukamy rozwiązania.

Solver, którego chcemy użyć wymaga następujących parametrów ode45(odefun, tspan, x0), gdzie odpowiednio:

odefun oznacza nazwę m-pliku zawierającego opis funkcji f(x(t), t),

tspan oznacza przedział czasowy [t_{0}, t_{1}],

x0 wektor oznaczający warunek początkowy x(t_{0}) = x_{0}.

Przygotujmy odpowiedni m-plik rownanie_vdp.m, z konkretną wartością epsilona:

function y = rownanie_vdp(t, x)
       
        y = [x(2); 0.1*(1-x(1))*x(2) - x(1)];
 
end

Teraz możemy rozwiązać równanie:

>> t0 =  0;
>> t1 = 60;
>> T = [t0, t1];
>> x0 = [0, .1];
>> % wywolujemy solver ode45
>> ode45('rownanie_vdp', T, x0)

I mozemy zobaczyć wykres rozwiązania:

Matlab4.png

Rys.4. Wykres rozwiązania równania dla t \in [0, 60], \epsilon = 0.1.

Toolbox-y

Toolbox-y to dodatkowe biblioteki do pakietu MATLAB. Z reguły są to zbiory m-plików zawierające specjalistyczne funkcje do określonych zastosowań, czasami mają także graficzny interfejs dla użytkownika. Toolbox'y mają swoje strony w pomocy MATLABa. Wśród tych dodatków warto wymienić:

  • Bioinformatics Toolbox Toolbox wpierający obliczenia związane z analizą sekwencji białkowych, między innymi:
    • przetwarzanie danych z baz bioinformatycznych,
    • analizę sekwencji,
    • analizę i wizualizację mikromacierzy.
  • Distributed Computing Toolbox Dodatek umożliwiający wykonywanie obliczeń MATLABa w środowisku rozproszonym.
  • Filter Design Toolbox Umoźliwia projektowanie, analizowanie oraz testowanie różnych filtrów cyfrowych. Jest to rozszerzenie możliwości toolbox-u Signal Processing Toolbox w szczególności o modelowanie filtrów typów:
    • FIR Filters,
    • IIR Filters,
    • Multirate Filters,
    • Filtry adaptacyje.
  • Image Processing Toolbox Toolbox zawierający zbiór funkcji rozszerzających możliwości MATLABa w manipulowaniu obrazami cyfrowymi. Poza podstawowymi operacjami dodatek ten pozwala na zaawansowane przetwarzanie obrazów, w szczególności:
    • płaskie transformacje,
    • przetwarzanie morfologiczne,
    • filtrowanie liniowe,
    • tranformaty,
    • analizę obrazów,
    • redukcję szumów.
  • Partial Differential Equation Toolbox Dodatek pozwalający rozwiązywać numerycznie niektóre równania różniczkowe cząstkowe za pomocą metody elementu skończonego. Toolbox posiada interfejs graficzny, do którego dostęp uzyskujemy komendą
>> pdetool

Za jego pomocą możemy sformułować zagadnienie, modyfikować parametry równania, zdefiniować 2-wymiarowy obszar na którym chcemy znaleźć rozwiązanie, skonstruować siatkę na tym obszarze, wyznaczyć rozwiązanie na siatce oraz narysować różne wykresy znalezionego rozwiązania.

  • Signal Processing Toolbox Zawiera szeroką gamę funkcji służących do przetwarzania sygnałów. Dodatek zawiera wiele funkcji wywoywanych wprost z wiersza poleceń, a także interfejs okienkowy, wywoływany poleceniem:
>> sptool
  • Statistics Toolbox Zawiera ponad 200 funkcji do zastosowań związanych ze statystyką matematyczną. Można za jego pomocą badać między innymi:
    • rozkłady prawdopodobieństwa,
    • modele liniowe i nieliniowe,
    • testowanie hipotez,
    • modele Markova.

Niektóre z narzędzi statystycznych posiądają interfejs graficzny, np. dystrybuanty rozkładów można analizować za pomocą narzędzia:

>> disttool

z kolei modele nieliniowe można badać za pomocą innego narzędzia:

>> nlintool 
  • Symbolic Math Toolbox Dodatek pozwalający wykonywać obliczenia symboliczne w środowisku MATLABa. Funkcje zawarte w tym dodatku bazują na języku obliczeń symbolicznych Maple i są traktowane jako rozszerzenie języka MATLABa. Można za ich pomocą wykonywać symbolicznie podstawowe operacje matematemaczne, różniczkowanie, całkowanie, rozwijać funkcje w szereg potęgowy, rozwiązywaćrównania, wykonywać operacje na macierzach, rozwiązywać zadania algebry liniowej i wiele innych.

MATLAB w ICM

MATLAB jest zainstalowany w ICM i dostępny dla użytkowników na komputerach:

  • halo,
  • rekin,
  • burza.

Uruchamianie pakietu:

  • należy przygotować środowisko pracy poleceniem:
use_matlab
  • uruchomic pakiet poleceniem:
matlab


Zobacz też:


Pakiety wzorowane na MATLABie, typu open-source:



Programowanie: OpenMP

Autor: Łukasz Bolikowski

W ramach poszerzania wiedzy o mechanizmach komunikacji równoległej przyszedł czas na OpenMP. Jest to zestaw tzw. dyrektyw, czyli jakby komentarzy, podpowiadających kompilatorowi w jaki sposób można zrównoleglić kod. OpenMP pozwala zrównoleglać programy napisane w językach Fortran i C. Jest to bardzo wygodne z punktu widzenia programisty rozwiązanie, ponieważ pozwala na bardzo szybkie zrównoleglenie istniejącego kodu. Wady to ograniczona stosowalność, np. w ICM: na halo maksymalnie 2 procesory, na tornado maksymalnie 16 SSP.

Model pamięci

OpenMP stosuje się w przypadku architektur o pamięci współdzielonej, czyli dla komputerów znajdujących się w ICM oznacza to:

  • dowolny węzeł (4 MSP / 16 SSP) komputera Cray X1e - tornado
  • dowolny węzeł (2 CPU) klastra halo

Przypomnijmy, model pamięci współdzielonej zakłada, że każdy procesor "widzi" całą dostępną pamięć, co redukuje komunikację pomiędzy procesorami.

Myśląc obrazowo: pamięć współdzielona to jeden duży stół, dookoła którego pracują robotnicy (procesory). Każdy widzi rezultaty pracy pozostałych i może z nich natychmiast skorzystać. Dla kontrastu, model pamięci rozproszonej zakłada, że każdy robotnik siedzi przy swoim małym stoliku, a rezultaty pracy "rzuca", lub "wykrzykuje" do innego zainteresowanego robotnika (procesora).

Bardziej szczegółowo o własnościach pamięci współdzielonej i rozproszonej, a także o różnicach pomiędzy nimi pisałem w numerze trzecim Biuletynu.

Pierwszy program

Zobaczmy na przykładzie, jak zrównoleglić program przy użyciu dyrektyw OpenMP. Wykorzystajmy w tym celu znany z poprzednich odcinków program obliczający wartość \pi korzystając ze wzoru \pi = 4 \int_0^1 \frac{1}{1+x^2}.

1.        program openmpi
2.        implicit none
3.        integer i, n
4.        real sumpi, mypart, x
5.        parameter (n = 1000000)
6.
7.        sumpi = 0.0
8.        do i = 1, n
9.          x = (i + 0.5) / n
10.         mypart = 1.0/(1.0 + x**2)
11.         sumpi = sumpi + mypart
12.       end do
13.       sumpi = 4.0 * sumpi / n
14.       print *, sumpi
15.       end program

Dla dużych wartości n, większość obliczeń wykonywanych jest w pętli w liniach 8-12. Chcielibyśmy więc podzielić pracę w ten sposób, aby każdy z procesorów "wziął" część iteracji pętli. W tym celu piszemy po prostu przed pętlą dyrektywę - informację dla kompilatora, że chcemy zrównoleglić tę pętlę:

1.        program openmpi
2.        implicit none
3.        integer i, n
4.        real sumpi, mypart, x
5.        parameter (n = 1000000)
6.
7.        sumpi = 0.0
8.  !$omp parallel do default(none)
9.  !$omp&  private(i, x, mypart)
10. !$omp&  shared(n, sumpi)
11.       do i = 1, n
12.         x = (i + 0.5) / n
13.         mypart = 1.0/(1.0 + x**2)
14. !$omp critical
15.         sumpi = sumpi + mypart
16. !$omp end critical
17.       end do
18.       sumpi = 4.0 * sumpi / n
19.       print *, sumpi
20.       end program

Pojawiło się kilka tajemniczych napisów, pora na wyjaśnienia. Zacznijmy od składni: !$omp na początku linijki, ewentualnie ze znakiem kontunuacji &, to informacja dla kompilatora, że linijkę należy traktować jako część dyrektywy OpenMP, a nie jako zwykły komentarz. parallel do, critical (i zamykające end critical) to dyrektywy, wszystko po nich (u nas: default(...), private(...), shared(...)) to dookreślenia dyrektyw.

Jak wstawiać dyrektywy

W Fortranie 77 dyrektywy sygnalizowane są pojawieniem się na początku linijki (od pierwszej kolumny) jednego z następujących przedrostków:

 !$OMP
 C$OMP
 *$OMP

Tak jak to się przyjęło w Fortranie 77, w 6. kolumnie można umieścić znak kontynuacji, jeśli treść dyrektywy nie zmieściła się w poprzedniej linijce.

W rozluźnionej składni Fortranu 90 dyrektywy poprzedzone muszą być:

 !$OMP

który nie musi rozpoczynać się od pierwszej kolumny, ale wtedy musi być poprzedzony spacjami. Kontynuacje linii zgodne ze zwyczajem Fortranu 90.

W języku C dyrektywy poprzedzamy:

 #pragma omp

Regiony równoległe

Dyrektywa parallel do dotyczy zawsze pętli znajdującej się pod nią, nie ma więc potrzeby (choć można) pisania end parallel do po pętli. Dyrektywa ta tworzy tzw. region równoległy, w którym praca dzielona jest pomiędzy procesory.

Wykonanie programu wygląda następująco: poza regionami równoległymi, kod wykonywany jest przez jeden procesor, tzw. master processor. Gdy natrafiamy na początek regionu równoległego, zatrudniane są pozostałe procesory, które przy kończeniu regionu równoległego są zwalniane. Jest to tzw. model fork-join, schematycznie przedstawiony na poniższym rysunku.

Model fork-join

Zasięg zmiennych

Konstrukcje default, private, shared wiążą się z bardzo ważnym w OpenMP pojęciem zasięgu zmiennych. Jak powszechnie wiadomo, całkowity brak własności prywatnej jest kiepską sprawą. Podobnie jest w świecie komputerów: czasem w trakcie obliczeń każdy z procesorów chciałby mieć swoje prywatne zmienne robocze. Z drugiej strony, warto mieć także zmienne wspólne, na przykład przechowujące końcowy wynik prac, czy stałe używane podczas obliczeń.

Tak więc w momencie, gdy otwierany jest region równoległy i pojawiają się procesory gotowe do pracy, należy stwierdzić: które ze zmiennych używanych w regionie równoległym są współdzielone (występować mają w jednej kopii, wspólnej dla wszystkich), a które są prywatne (każdy z procesorów otrzyma kopię do prywatnego użytku).

Wracając do naszego programu, przyjrzyjmy się po kolei zmiennym używanym w regionie równoległym i ustalmy ich zakres (współdzielona - shared, czy prywatna - private):

  • sumpi to suma częściowa, na którą pracują wszystkie procesory. Każdy z nich dorzuca swój wynik cząstkowy do tej wspólnej zmiennej. Czyli: shared.
  • n to stała. Nie ma potrzeby, aby procesory miały własne kopie wartości, która w żaden sposób się nie zmienia. Werdykt: shared.
  • x to robocza zmienna używana do obliczenia, dla danej iteracji, wartości x na podstawie i. Każdy procesor powinien mieć swoją prywatną wartość, a więc: private.
  • mypart jest wkładem danej iteracji w całkowitą sumę. Jest więc zmienną roboczą, jej wartość nie jest używana poza daną iteracją: private.
  • i jest zmienną, po której iterowana jest zrównoleglana pętla. Standard OpenMP wymusza, aby była to zmienna private, co jest skądinąd intuicyjne.

Region krytyczny

Pozostaje wyjaśnienie dyrektywy critical. Zauważmy, że gdy dwa procesory wykonują jednocześnie linię 15. zrównoleglonego kodu, to następuje jednoczesny zapis zapewne różnych wartości do tej samej komórki pamięci (bo sumpi jest zmienną współdzieloną). Takie zachowanie jest niedopuszczalne, w większości wypadków oznacza to błędnie zrównoleglony kod, gdyż w gruncie rzeczy stan komórki pamięci po tych operacjach jest nieokreślony.

Powinniśmy więc zagwarantować, że nie nastąpi jednoczesne wykonywanie linii 15. przez dwa lub więcej procesory. W tym celu tworzymy tzw. region krytyczny, w którym może przebywać jednocześnie co najwyżej jeden procesor. O dyrektywie critical można można myśleć jak o barierze, przed którą ustawiają się kolejne gotowe procesory, czekając aż region krytyczny będzie wolny.

Skąd się biorą różnice w wynikach?

Po kilkukrotnym uruchomieniu powyższego kodu na wielu procesorach zauważymy, że za każdym razem otrzymujemy różne wyniki. Powód? Operacja dodawania w arytmetyce zmiennoprzecinkowej nie jest łączna, tzn. nie zawsze (a+b)+c=a+(b+c).

W naszym przypadku, przy każdym uruchomieniu programu procesory wchodzą do regionu krytycznego w innej kolejności, a więc inna jest także kolejność dodawania składników sumy sumpi.

Chcąc uzyskać, np. dla celów debugowania, powtarzalność obliczeń, możemy zamiast dyrektywy critical użyć ordered, która działa z grubsza rzecz biorąc tak samo, ale dodatkowo wymusza, aby procesory weszły do regionu krytycznego dokładnie w tej kolejności, w której weszłyby, gdyby kod wykonywany był na jednym procesorze. Zauważmy, że użycie dyrektywy ordered może w przypadku dużych obliczeń spowolnić nieco czas wykonywania pętli, bo może się zdarzyć, że procesory będą czekać przed wolnym regionem krytycznym na marudera o niższym numerze i.

Nie jest prawdą, że użycie dyrektywy ordered daje dokładne/dokładniejsze wyniki. W większości wypadków wyniki uzyskane przy użyciu orderedrównie niedokładne jak wyniki z critical.

Wydajność: co robić, czego nie robić

Jak zostało wspomniane wyżej, należy unikać dyrektywy ordered. Co więcej, należy również unikać dyrektywy critical, ponieważ wprowadza ona dającą duży narzut czasowy barierę.

Oczywista uwaga: im większa część kodu jest zrównoleglona, tym szybciej (zazwyczaj) kod działa. Mniej oczywista i intuicyjna jest natomiast kara za niezrównoleglenie. Załóżmy, że zrównoleglony został kod zajmujący oryginalnie 80% czasu obliczeń. Taki kod, uruchamiany np. na 8 procesorach, będzie wykonywał się zaledwie ok. 3.3x szybciej, niż kod jednoprocesorowy. To wynik prostych obliczeń, zwanych poważniej prawem Amdahla. Ta obserwacja sugerowałaby, że chcąc liczyć na wielu procesorach, należy bezwzględnie starać się zrównoleglać wszystkie możliwe fragmenty programu.

Prawo Amdahla po zrownolegleniu 80% kodu

Jest jednak druga strona medalu: zrównoleglanie wprowadza dodatkowy narzut czasowy, który może de facto spowolnić wykonanie kodu. Warto więc sprawdzać, czy zrównoleglenie rzeczywiście przekłada się na skrócenie czasu obliczeń.

Warto także pamiętać, że otworzenie i zamknięcie regionu równoległego jest bardzo kosztowne. Dlatego warto łączyć kilka obszarów równoległych w jeden, oszczędzając przy tym na inicjalizacji procesorów. Dokonuje się tego rozdzielając kilka dyrektyw parallel do na jedną dyrektywę parallel oraz kilka dyrektyw do. Z braku miejsca modyfikacja ta nie zostanie tu szczegółowo opisana, zachęcam do przejrzenia dokumentacji OpenMP.

Rozbicie dyrektywy parallel-do

Inkrementacyjne zrównoleglanie

Jako podstawową zaletę OpenMP wymienia się fakt, że nie wymaga ono przepisywania kodu "od zera". Zamiast tego, możemy zacząć od kodu jednoprocesorowego i stopniowo zrównoleglać kolejne jego fragmenty. W każdym punkcie prac mamy działający kod, który możemy testować, debugować, lub używać do rzeczywistych obliczeń, jeśli jest już wystarczająco szybki.

Jak kompilować i uruchamiać

Na tornado dyrektywy OpenMP są rozpoznawane przez kompilator automatycznie. Proszę pamiętać, że kompilując z przeznaczeniem na procesor MSP można będzie użyć do 4 procesorów, a w przypadku kompilacji na SSP 16 takich procesorów. Aby uruchomić program na określonej liczbie procesorów używamy polecenia aprun, np. uruchomienie openmpi.x na 3 procesorach realizujemy przez:

 aprun -d 3 ./openmpi.x

Na klastrze halo kompilując kompilatorem Portland Group należy dodać opcję -mp. Przykładowa kompilacja:

 use_pgi
 pgf77 -mp openmpi.f -o openmpi.x

i przykładowe uruchomienie:

 setenv OMP_NUM_THREADS 2
 ./openmpi.x

Oczywiście obliczenia należy wykonywać za pośrednictwem systemu kolejkowego. W skrypcie dla systemu kolejkowego proszę dodać instrukcję:

 #PBS -l nodes=1:ppn=2

mówiącą, że chcemy użyć oba procesory jednego węzła.

Dokumentacja

  • Standard OpenMP
  • CrayDoc, szczególnie dokumenty:
    • S-3901-52 (Cray Fortran CompilerTM Commands and Directives Reference Manual), rozdział 6
    • S-2388-52 (Man Page Collection: OpenMP Library Routines)
  • Szkolenie z OpenMP znalezione na stronie LLNL

Życzenia

Autorzy: Redakcja

Z okazji zbliżających się świąt Bożego Narodzenia i nadchodzącego Nowego Roku, redakcja Biuletynu życzy czytelnikom dużo pomyślności, radości i spokoju, oraz pustych kolejek w systemie PBS.

Wesołych Świąt!