Za dużo naraz

Chociaż wieloprocesorowe i wielordzeniowe konstrukcje nie są nowością, bardzo mało aplikacji i gier korzysta z ich mocy. Optymalne zaprogramowanie współpracy kilku rdzeni nie jest takie łatwe.


Chociaż wieloprocesorowe i wielordzeniowe konstrukcje nie są nowością, bardzo mało aplikacji i gier korzysta z ich mocy. Optymalne zaprogramowanie współpracy kilku rdzeni nie jest takie łatwe.

Menedżer zadań umożliwia zmianę priorytetu.

Menedżer zadań umożliwia zmianę priorytetu.

Ogłoszono je przyszłością informatyki, pozwalającymi na przedłużenie obowiązywania prawa Moore'a i najbardziej inteligentnymi układami, jakie kiedykolwiek wymyślono. Jednak wielordzeniowe procesory nie są lekarstwem na wszystkie problemy informatyki. Nie wystarczy zastąpić nimi pojedyncze jednostki, żeby wszystko liczyło się sprawniej niż dotąd.

Oczywiście AMD na temat X2 twierdzi coś innego, a Intel z czterordzeniowym QX6700 Extreme roześmieje się prosto w oczy, jeśli zasugerujesz, że ich produkt więcej problemów przysparza niż rozwiązuje. Osoby, które nie mają bliskiego kontaktu z programowaniem, łatwo dadzą się przekonać, że wielordzeniowość jest wynalazkiem, o którym marzyły. Niestety to nieprawda. Programowanie wielordzeniowe jest trudne i nie daje się zautomatyzować. Zanim wyjaśnimy przyczyny trudności, poświęcimy nieco miejsca podstawom.

Pierwszy i ostatni

Na początek warto ustalić fakty i wyjaśnić różnice między wieloma zadaniami i wątkami. Wielozadaniowość generuje się na poziomie systemu operacyjnego. Na przykład praca dwóch różnych aplikacji, takich jak Photoshop i Outlook, w tym samym czasie zasługuje na tę nazwę. Oba programy działają zupełnie niezależnie, korzystając z własnych, oddzielonych od siebie obszarów pamięci. Mogą być nieświadome swojego istnienia i pracować tak, jakby miały cały komputer do swojej dyspozycji. Tylko system operacyjny zna prawdziwy stan rzeczy i w wyjątkowych wypadkach może udzielić aplikacjom informacji o innych jednocześnie uruchomionych programach. Wątki są bardziej zależne od siebie i mają wiele wspólnych ze sobą danych.

Często przeklinamy systemy Microsoftu za błędy, ale ich wielozadaniowość jest bardzo skutecznie zarządzana. Pamiętajmy, że jednordzeniowy procesor może wykonywać tylko jedno zadanie naraz, więc wrażenie jednoczesnej pracy wielu programów musi być czystą iluzją. Odnosimy to wrażenie dzięki dzieleniu czasu CPU pomiędzy kilka aplikacji i szybkiemu przełączaniu pomiędzy nimi. Ta czynność zaczyna się od zapamiętania tzw. kontekstu, czyli wszystkich danych specyficznych dla przerywanego procesu, umożliwiających jego kontynuowanie, przywrócenia kontekstu następnego programu, wykonywaniu jego części przez krótki czas, zapamiętania kontekstu, następnego przełączenia itd. Jeśli CPU wymienia aplikacje co kilka milisekund, odnosimy wrażenie, jakby wszystkie pracowały równocześnie.

W zasadzie istnieją dwa rodzaje wielozadaniowości: system z wywłaszczeniem albo bez. Drugi z nich jest prostszy w implementacji i był stosowany w starszych systemach operacyjnych, począwszy od komputerów Acorn Archimedes w późnych latach 80. ubiegłego wieku. W takim układzie aplikacja ma sama dbać o sprawiedliwy przydział czasu. Jeśli zażąda dostępu do zasobów komputera - otrzymuje je. Jeśli jednak jest napisana z błędami i nie zwolni tego dostępu lub nie odda sterowania do jądra - komputer się zawiesza.

W systemie z wywłaszczaniem to on pilnuje porządku i przydziela aplikacjom małe odcinki czasu pracy komputera. Kiedy dany okres mija, system gwałtownie przerywa proces, zapamiętuje aktualny kontekst, zabiera zasoby procesora i przydziela następnemu programowi.

W praktyce system liczy się także z priorytetami poszczególnych procesów. Ważniejsze zadania realizowane przez system mogą wywłaszczać mniej ważne. Windows XP czy Vista mają planistę wybierającego program, który otrzyma zasoby procesora w następnej kolejności. Te z wyższą pozycją w hierarchii oczywiście mają pierwszeństwo.

Priorytet poszczególnych procesów można także nadać manualnie. Wystarczy otworzyć Menedżera zadań z klawiatury: [Ctrl Alt Del] lub klikając prawym przyciskiem myszy pasek zadań i rozwijające się menu. Wybrawszy kartę Procesy, zobaczymy listę, gdzie wymienione są osobne aplikacje, pracujące pod kontrolą systemu z wywłaszczeniem. Karta Widok | Wybierz kolumny | Priorytet podstawowy ujawni wagę każdego z nich. Można ją zmienić, klikającprawym przyciskiem wiersz procesu i wybierając Ustaw priorytet. Do wyboru jest sześć możliwości, od Czasu rzeczywistego do Niskiego.

Im więcej, tym lepiej

Powodem, dla którego w tekście o wielu rdzeniach opowiadamy o wielozadaniowości, jest pokazanie, jak dobrze obie cechy pasują do siebie na poziomie systemu operacyjnego. Większość procesorów tylko ułatwia rozdzielenie zasobów komputera na większą liczbę jednocześnie wykonywanych zadań. To prosta robota, skoro poszczególne procesy nie mają ze sobą nic wspólnego. Praca Outlooka z naszego przykładu nie będzie przeszkadzała aplikowaniu filtrów ulubionym fotografiom w Photoshopie. Przecież oba używają osobnych obszarów pamięci wirtualnej. W praktyce czynnych procesów jest o wiele więcej i będą one dzielić się zasobami komputera tym łatwiej, im więcej rdzeni ma do dyspozycji system operacyjny.

Ten optymistyczny obraz straci wiele blasku, jeśli uświadomimy sobie, że jednoczesne wykonywanie wielu rzeczy wcale nie jest głównym celem właścicieli komputera. Najczęściej chodzi o coś innego - jak najszybsze wykonanie jednej aplikacji, przejście wybranej gry czy kodowanie multimediów. Niewiele osób może równać się z Napoleonem i zajmować się wieloma czynnościami naraz. Raczej jesteśmy przyzwyczajeni do realizacji pojedynczych zadań, jednego po drugim. Dlatego gra na pianinie wymaga tak długich ćwiczeń. Nie jest więc jasne, ilu użytkowników na świecie mogłoby efektywnie panować nad wieloma rzeczami, którymi komputer zajmuje się w tym samym momencie.

Do konkretów

Wiemy już, że system operacyjny nie ma problemu z wielozadaniowością, ponieważ poszczególne procesy nie są ze sobą powiązane. Z drugiej strony, ludzie także nie mają kłopotów z myśleniem o wydarzeniach, które zachodzą jedno po drugim, w sekwencyjnym przebiegu. Obie dobrze wydeptane ścieżki okazują się zupełnie nieprzydatne, kiedy stajemy przed problemem jak najszybszego wykonania programu za pomocą wielordzeniowego procesora. Windows tu niewiele pomoże, gdyż radzi sobie tylko z odseparowanymi procesami. Chciałoby się napisać program działający jednocześnie na kilku procesorach, ale to wymaga zmiany sposobu myślenia, z sekwencyjnego na równoległy. Kto jest do tego zdolny? Świat programowania równoległego sprawia wrażenie konceptualnego węzła, który nie jest łatwo rozwiązać. Spróbujmy przybliżyć problem na przykładzie.