Myślę, że najlepszym sposobem opisu architektury superkomputera Beowulf
jest użycie przykładu, który jest bardzo podobny do prawdziwego Beowulf'a, ale
znany większości administratorów systemu. Przykład najbliższy Beowulf'owi to
laboratorium komputerów Unix z serwerem i klientami. Aby być bardziej
szczegółowym użyję jako przykładu laboratorium komputerów DEC Alpha na
Katedrze Nauk Komputerowych, USQ. Serwer nazywa się beldin, a klienci
nazywają się scilab01, scilab02, aż do scilab20. Wszyscy
klienci mają zainstalowaną lokalną kopię systemu operacyjnego Digital Unix
4.0, ale korzystają z katalogów użytkownika (/home) oraz
/usr/local serwera poprzez NFS (Network File System). Każdy klient
posiada wpis dla serwera i wszystkich pozostałych klientów w swoim pliku
/etc/hosts.equiv, więc wszyscy klienci mogą uruchomić rsh na każdym
innym. Serwer jest jednocześnie serwerem NIS dla całego laboratorium, więc
informacje księgowania są identyczne dla wszystkich maszyn. Osoba może
siedzieć przed konsolą scilab02, zalogować się i pracować w tym samym
środowisku, w jakim pracowała by gdyby zalogowała się z serwera bądz z
scilab15. Spowodowane jest to tym, że system operacyjny na wszystkich
komputerach jest zainstalowany i skonfigurowany w ten sam sposób, a katalogi
użytkownika /home i /usr/local mieszczą się fizycznie na
serwerze, i są udostępniane przez NFS. Więcej informacji o NIS i NFS
znajdziesz w dokumentach HOWTO
NIS oraz
NFS.
Gdy mamy już jakieś pojęcie o architekturze systemu, możemy spojrzeć jak
wykorzystać dostępne cykle CPU maszyn w laboratorium komputerowym.
Każda osoba może zalogować się na dowolnej maszynie, i uruchomić program i
swoim katalogu domowym, ale może także wykonać to zadanie na innej maszynie
wywołując po prostu odległą powłokę. Przykładowo załóżmy że chcemy obliczyć
sumę pierwiastków kwadratowych wszystkich liczb całkowitych od 1 do 10
włącznie. Piszemy prosty program nazwany sigmasqrt (patrz
kod źródłowy), który wykonuje oblicznia. Aby obliczyć
sumę pierwiastków kwadratowych liczb od 1 do 10 wykonujemy:
[jacek@beldin sigmasqrt]$ time ./sigmasqrt 1 10 22.468278 real 0m0.029s user 0m0.001s sys 0m0.024sKomenda
time pozwala nam śledzić upływ czasu podczas wykonywania
zadania. Jak widać, ten przykład zajął jedynie mały ułamek sekundy (0.029s),
ale co będzie jeśli spróbujemy dodać pierwiastki kwadratowe liczb od 1 do
1000000000? Spróbujmy, ponownie obliczając upływ czasu.
[jacek@beldin sigmasqrt]$ time ./sigmasqrt 1 1000000000 21081851083600.559000 real 16m45.937s user 16m43.527s sys 0m0.108s
Tym razem wykonianie programu trwało znacznie dłużej. Oczywistym pytaniem jest co możemy zrobić aby przyspieszyć wykonanie programu? Jak możemy zmienić sposób wykonania zadania aby zmniejszyć upływ czasu? Oczywistą odpowiedzią jest rozbicie zadania na wiele pod-zadań równoległych na wszystkich komputerach. Możemy rozbić jedno duże zadanie dodawania na 20 części, obliczając jeden zakres pierwiastków kwadratowych i dodając je na każdym węźle. Gdy wszystkie węzły zakończą obliczenia i zwrócą rezultaty, 20 liczb powinno zostać dodanych do siebie aby otrzymać końcowy wynik.
[jacek@beldin sigmasqrt]$ mkfifo output [jacek@beldin sigmasqrt]$ ./prun.sh & time cat output | ./sum [1] 5085 21081851083600.941000 [1]+ Done ./prun.sh real 0m58.539s user 0m0.061s sys 0m0.206s
Tym razem zajęło to około 58.5s. Jest to czas od rozpoczęcia zadania do zakończenia go przez wszystkie węzły i zwrócenia rezultatu przez potok. Ten czas nie zawiera końcowego dodania 20 liczb, ale to jedynie mały ułamek sekundy, który może zostać zignorowany. Zauważamy że nastąpiła znaczna poprawa przy równoległym wykonaniu zadania. Równoległe zadanie wykonało się ponad 17 razy szybciej, co jest bardzo dobrym wynikiem przy 20-krotnym zwiększeniu ilości CPU. Powyższy przykład ma na celu zilustrowanie najprostszej metody zmiany zwykłego kodu na równoległy. W praktyce takie proste przypadki są niezwykle rzadkie, i różne techniki (takie jak API PVM i PMI) są wykorzystywane do osiągnięcia równoległości.
Laboratorium komputerowe opisane powyżej jest doskonałym przykładem klastra stacji roboczych (COW). Tak więc co jest szczególnego w Beowulf'ie, i w jaki sposób różni się on od COW? Prawdą jest, że nie jest to wielka różnica, ale Beowulf posiada kilka unikalnych cech. Po pierwsze, w większości przypadków węzły-klienci klastra Beowulf nie posiadają klawiatury, myszy, karty graficznej czy monitora. Dostęp do węzłów-klientów odbywa się poprzez odległe połączenia z węzła-serwera, dedykowanego węzła-konsoli lub konsoli szeregowej. Jako że węzły-klienci nie muszą mieć dostępu do maszyn spoza klastra, ani maszyny spoza klastra nie muszą mieć bezpośredniego dostępu do węzłów-klientów, powszechnie stosowaną praktyką jest nadawanie węzłom-klientom prywatnych adresów IP, z prywatnych zakresów takich jak 10.0.0.0/8 czy 192.168.0.0/16 (RFC 1918 http://www.alternic.net/rfcs/1900/rfc1918.txt.html). Na ogół jedyną maszyną podłączoną do świata zewnętrznego za pomocą drugiej karty sieciowej jest węzeł-serwer. Najczęściej korzysta się z systemu poprzez bezpośredni dostęp do konsoli serwera, lub poprzez telnet czy odległe logowanie na serwer z odległej stacji roboczej. Na serwerze użytkownicy mogą edytować i kompilować swój kod, a także uruchamiać procesy na wszystkich węzłach w klastrze. W większości przypadków systemy COW są używane do obliczeń równoległych w nocy i w weekendy, gdy użytkownicy nie korzystają ze swoich stacji roboczych do pracy, wykorzystując w ten sposób z niepotrzebne cykle procesora. Z kolei maszyna Beowulf jest maszyną dedykowaną do przetwarzania równoległego, i zoptymalizowaną w tym celu. Beowulf zapewnia także większy współczynnik ceny do wydajności, jako że jest zbudowany z ogólnie dostępnych komponentów i korzysta na ogół z darmowego oprogramowania. Beowulf ma także więcej cech pojedynczego systemu, które pomagają użytkownikom dostrzegać klaster Beowulf jako pojedynczą obliczeniową stację roboczą.