48
1 Programowanie współbieżne i równoległe dr inż. Marcin Wilczewski 2018/2019

Programowanie współbieżne i równoległe · 2019. 1. 14. · Paradygmaty programowania •Programowanie proceduralne •Programowanie obiektowe •Programowanie współbieżne

  • Upload
    others

  • View
    8

  • Download
    0

Embed Size (px)

Citation preview

  • 1

    Programowanie współbieżnei równoległe

    dr inż. Marcin Wilczewski2018/2019

  • 2

    Cel wykładu

    Przedstawienie zagadnień projektowania oraz programowania rozwiązań współbieżnych i równoległych

    Tematyka wykładu

    • Wątki i procesy

    • Systemy z pamięcią współdzieloną oraz systemy rozproszone

    • Poprawność programów współbieżnych

    • Przegląd klasycznych problemów współbieżności oraz ich rozwiązania

    • Komunikacja i synchronizacja. Synchronizacja w systemach baz danych

    • Programowanie współbieżne w Javie i/lub Pythonie.

    •Techniki programowania współbieżnego

  • 3

    Organizacja zajęć

    Laboratorium:

    Zasady oceniania

    Ocenianie: z przedmiotu można otrzymać maksymalnie 40 punktów, w tym: maks. 30 punktów laboratorium + maks. 10 punktów wykład.

    Pisemne zaliczenie jest opcjonalne. Nie jest wymagane do zaliczenia przedmiotu (patrz skala ocen poniżej).

    Termin pisemnego zaliczenia przedmiotu: ostatnie zajęcia w semestrze

    Skala punktacji + oceny:

    20,5:22,0 – 3,0

    22,5:27,0 – 3,5

    27,5:32,0 – 4,0

    32,5: 37,0 – 4,5

    37,5: 40,0 – 5,0

  • 4

    Paradygmaty programowania

    • Programowanie proceduralne

    • Programowanie obiektowe

    • Programowanie współbieżne – obejmuje projektowanie i tworzenie programów, które w fazie wykonania składają się z co najmniej dwóch jednostek wykonywanych współbieżnie (każdy z nich niezależnie jest wykonywany sekwencyjnie). Wykonywanie współbieżne może wymagać zapewnienia komunikacji/synchronizacji pomiędzy jednostkami konkurującymi o dostęp do zasobów współdzielonych

    • Programowanie równoległe

    • Równoległość. Jednoczesność. Współbieżność

    • Współbieżnie: jedna jednostka wykonania rozpoczyna swoją pracę zanim druga zakończy swoje działanie. Obliczenia współbieżne mogą być wykonywane w systemach jedno- i wieloprocesorowych

    • Z czego wynika potrzeba współbieżności?

    • Kiedy możliwe jest osiągnięcie przetwarzania równoległego?

    • Nie wszystkie procesy współbieżne są równie ciekawe: procesy interakcyjne, procesy niezależne

  • 5

    Motywacja i korzyści programowania równoległego i współbieżnego

    • Interakcyjność systemu / zdolność do reagowania: Wielowątkowość może umożliwiać interakcję z użytkownikiem mimo zablokowania części aplikacji lub wykonywania przez nią długich operacji. Przetwarzanie współbieżne (nawet w środowiskach jednoprocesorowych) pozwala na dekompozycję funkcjonalną zadań/programów (niezależne przetwarzanie danych, operacje IO, komunikacja z użytkownikiem, etc.). Przykład: edytory tekstu, aplikacje webowe, …

    • Przyspieszenie obliczeń: Przetwarzanie współbieżne/równoległe może zapewnić przyspieszenie obliczeń w stosunku do przetwarzania sekwencyjnego. Rosną wymagania dotyczące szybkości i liczby wykonywanych zadań/operacji. Model programowania wielowątkowego daje duże możliwości

    • Wykorzystanie architektury wieloprocesorowej: Korzyści z wielowątkowości zwiększają się w architekturach wieloprocesorowych, gdzie każdy wątek może działać na odrębnym procesorze

    • Intuicyjność modelowania: Model współbieżny rozwiązania pewnych problemów jest modelem najbardziej naturalnym i najbliższym rzeczywistemu problemowi (modelowanemu zjawisku). Wielka liczba procesów rzeczywistych ma naturę współbieżną/równoległą, np. procesy produkcyjne/operacyjne, procesy biologiczne

    • Ekonomia przetwarzania: podział na wątki oszczędza czas zarządzania aplikacją

  • 6

    Programowanie współbieżne vs programowanie równoległe

    • Obliczenia współbieżne stanowią szerszą klasę niż obliczenia równoległe (mogą być wykonywane zarówno w systemach jedno- jak i wieloprocesorowych)

    • Komputery współcześnie produkowane to maszyny wieloprocesorowe (wielordzeniowe). Programowanie równoległe i współbieżne zapewnia wykorzystanie mocy zapewnianej na poziomie sprzętowym (fizycznym)

    • Nawet w przypadku architektur wieloprocesorowych, gdy liczba procesów gotowych do wykonania przekracza liczbę procesów wykonywane są one współbieżnie (pozornie równolegle), a nie faktycznie równolegle

  • 7

    Obszary wykorzystania programowania współbieżnego i równoległego

    • Systemy operacyjne (wielozadaniowość)

    • Systemy baz danych (wielozadaniowość, wielodostęp)

    • Obliczenia na potrzeby nauki, biznesu, inżynierii,…

    • Gry komputerowe

    • Systemy wbudowane (urządzenia mobilne, urządzenia AGD)

    • Systemy czasu rzeczywistego (systemy produkcyjne)

  • 8

    Programy współbieżne i przeplot (1)

    • Program sekwencyjny składa się deklaracji zmiennych oraz instrukcji zapisanych w języku programowania. Podczas fazy wykonania porządek instrukcji programu sekwencyjnego dla tych samych danych wejściowych jest stały

    • Program współbieżny jest zbiorem programów sekwencyjnych wykonywanych abstrakcyjnie współbieżnie

    • Program sekwencyjny będący elementem programu współbieżnego jest nazywany procesem lub wątkiem

    • W przypadku programów współbieżnych stwierdzenie o stałej kolejności wykonania instrukcji procesów (programów składowych) w ogólności nie jest prawdziwe.

    • Każdy możliwy ciąg wykonań kolejnych akcji/instrukcji procesów sekwencyjnych programu współbieżnego stanowi przeplot

  • 9

    Programy współbieżne i przeplot (2)

    • Projektując programy współbieżne nie można założyć, że

    • pewne przeploty są niemożliwe do zrealizowania. Eliminacja możliwych, niepożądanych przeplotów powinna odbywać się na etapie projektowania rozwiązania i jest osiągana m. in. przez synchronizację procesów

    • procesy będą wykonywane równolegle (w tym samym czasie) przez fizycznie odrębne procesory. Faktyczną równoległość można osiągnąć w systemach wieloprocesorowych. Efekt współbieżności w systemach jednoprocesorowych (lub systemach, gdzie liczba procesorów jest mniejsza niż liczba procesów) jest realizowana przez podział czasu procesorów. Systemy tego typu to systemy z podziałem czasu

    • znana jest względna lub bezwzględna szybkość wykonywania procesów

    1 2

    A B

    1 2 A B

    1 A B 2

    1 A 2 B

    A B 1 2

    A 1 2 B

    A 1 B 2

    P1

    P2

    procesy

    możliwe przeploty

    instrukcje składowe

  • 10

    Problemy programowania współbieżnego

    • Główne problemy programowania współbieżnego wynikają z konieczności zapewnienia odpowiedniej interakcji pomiędzy procesami oraz uporządkowania instrukcji atomowych wykonywanych przez poszczególne procesy (wykluczenie niepożądanych przeplotów)

    • Interakcję pomiędzy współbieżnie wykonywanymi procesami realizuje się poprzez komunikację oraz w szczególności synchronizację (zapewnienie ustalonego porządku wykonywania operacji przez procesy) wykluczającą określone przeploty

    • Konieczność synchronizacji pojawia się gdy: jeden proces potrzebuje dostępu do danych generowanych lub aktualizowanych przez inny proces lub w przypadku dostępu procesów do zasobów współdzielonych.

    • Analiza poprawności programu współbieżnego powinna zawierać analizę wszystkich możliwych przeplotów procesów. Dowodem wprost niepoprawności programu współbieżnego jest wykazanie możliwości wystąpienia niepożądanego przeplotu. Nie jest istotne prawdopodobieństwo wystąpienia takiego niepożądanego przeplotu

    • W ogólności nie jest możliwe wskazanie liczby testów (wykonań programu współbieżnego) dowodzących poprawności programu

  • 11

    Przykład problemu w programach współbieżnych: wyścigi (race)

    • Więcej niż jeden wątek korzysta jednocześnie z zasobu dzielonego, przy czym co najmniej jeden próbuje go zmienić

    • Przyczyna niedeterministycznego zachowania się programu współbieżnego. Niedeterminizm oznacza nieokreśloność kolejności wykonania się kodu programu współbieżnego

    • Może prowadzić do trudnych do wykrycia błędów

    • To czy wyścig fizycznie wystąpi zależy od sposobu przydziału czasu procesora poszczególnym wątkom konkurującym o zasób

    • Problem wyścigów co najmniej częściowo wynika z faktu złożonego charakteru wykonywanych instrukcji: aktualizacja zasobu dzielonego (np. zmiennej globalnej) składa się z kilku atomowych instrukcji: odczytu, modyfikacji, zapisu

    • Wyścig można wyeliminować poprzez zapewnienie, że złożone operacje wykonywane są w sposób niepodzielny i wyłączny wzajemne wykluczanie

  • Zrównoleglanie. Prawo Amdhala (1/4)

    •W przypadku idealnym zastąpienie 1 procesora n procesorami powinno skutkować n-krotnym przyspieszeniem (zwiększenie mocy obliczeniowej). W praktyce, w ogólności nie jest to osiągalne ze względu na:

    • Problem nie zawsze jest możliwy do podzielenia na n procesów jednakowej długości,

    • W ogólności mogą wystąpić składowe problemu, które należy wykonać sekwencyjnie (a nie równolegle)

    • Czas koordynacji procesów jest niezerowy

    •Przykład niepodzielnej części sekwencyjnej:a = b+cd = a + ce = d +bObliczenia zmiennych muszą być wykonane w sekwencji: jedna po drugiej.

  • Zrównoleglanie. Prawo Amdhala (2/4)

    Procesor 1 Procesor 1

    Procesor 2

    Procesor 3

    Procesor 4

    Procesor 5

    Pojedynczy procesor wykonuje zadanie w ciągu 5 jednostek czasu

    5 procesorów wykonuje zadanie w ciągu 1 jednostki czasu. Idealne zrównoleglenie (5x). Możliwy podział na 5 podzadań jednakowej długości.

    •Przykład 2: zadanie złożone z 5 podzadań, gdzie 1 jest 2 krotnie trudniejsze od pozostałych (podzadania są nierównej długości)

    Procesor 1

    Pojedynczy procesor wykonuje zadanie w ciągu 6 jednostek czasu

    Procesor 1

    Procesor 2

    Procesor 3

    Procesor 4

    Procesor 5

    5 procesorów wykonuje zadanie w ciągu 2 jednostek czasu. Zrównoleglenie zredukowało czas z 6 jednostek do 2 jednostek czasu. Przyspieszenie 3x.

    •Przykład 1: zadanie złożone z 5 podzadań jednakowej długości

  • Zrównoleglanie. Prawo Amdhala (3/4)

    •Prawo Amdhala definiuje wartość przyspieszenia (speedup) możliwego do zrealizowania przez zrównoleglenie jako stosunek czasu potrzebnego jednemu procesorowi na wykonanie zadania do czasu potrzebnego n współbieżnym procesorom na wykonanie tego samego zadania

    S = 1 / ( 1 – p + p/n ),

    gdzie p – ułamek pracy, która może być wykonana równolegle, n liczba dostępnych współbieżnych procesorów.

    •Przykład: zadanie złożone z 5 podzadań, gdzie 1 jest 2 krotnie trudniejsze (wymaga przetwarzania sekwencyjnego) od pozostałych. p = 5/6 = 0,83, n=5 S = 3.

    •Przykład: zadanie złożone z 20 podzadań, gdzie 1 jest 2 krotnie trudniejsze od pozostałych. p = 20/21 = 0,95, n=20 S = 10,5.

    •Zgodnie z prawem Amdhala: wielkość przyspieszenia każdego złożonego zadania jest ograniczona przez zadania, które muszą być wykonane sekwencyjnie. Sposób zrównoleglenia przedstawiony w przykładach nie jest optymalny, jednak zrównoleglenie pozostałych 0,05 problemu (udało się zrównoleglić 20/21=0,95) wymaga komunikacji i koordynacji procesów.

  • Zrównoleglanie. Prawo Amdhala (4/4)

    Prawo Amdhala. Zależność przyspieszenia od liczby procesorów dla ustalonego poziomu zrównoleglenia problemu. Widoczny efekt nasycania się krzywych przyspieszenia.

    •W granicy nieskończonej liczby procesorów wartość przyspieszenia zmierza do 1/(1-p).

    •W zależności od poziomu zrównoleglenia (p) krzywa przyspieszenia nasyca się. Powyżej pewnego progu zwiększanie liczby procesorów nie przynosi zysku czasowego (brak realnego przyspieszenia).

    •Prawo Amdhala jest modelem (uproszczeniem) procesu zrównoleglenia. Zakłada się w nim, że: zarządzanie procesami jest bezkosztowe (zerowy czas) oraz zadania można dzielić idealnie pomiędzy procesory.

    0

    5

    10

    15

    20

    25

    2 4 8 16 32 64 128

    256

    512

    1024

    2048

    4096

    8192

    S

    Liczba procesorów (n)

    p=0,95 p=0,9 p=0,75

  • 16

    Procesy i wątki - pojęcia

    • Program – pojęcie statyczne obejmujące m. in. kod zapisany w określonym języku programowania

    • Proces – jednostka programowa w trakcie wykonywania wraz z przydzielanymi dynamicznie przez system zasobami. System operacyjny zapewnia wzajemną izolację procesów (bezpieczeństwo przetwarzania)

    • W wielozadaniowych systemach operacyjnych możliwe jest współbieżne lub równoległe wykonywanie wielu procesów

    • Każdy proces posiada kod, segment danych (zmienne globalne), stos (adresy powrotu z wywoływanych procedur) oraz zmienne lokalne oraz rejestry

    • Wątki są jednostkami przetwarzania wydzielonymi w ramach procesu. Można je interpretować jako sekwencję instrukcji do wykonania, które mogą być wykonywane współbieżnie z innymi sekwencjami instrukcji należącymi do tego samego lub innego procesu

    • Wątki posiadają wspólny kod oraz dane (współdzielą zmienne globalne), niezależne stosy (zmienne lokalne) i rejestry. Wątki mają dostęp do pamięci współdzielonej

    • Każdy proces posiada co najmniej jeden wątek

  • 17

    Procesy i wątki. Porównanie

    Procesy

    • Nie dzielą pamięci

    • Nie jest potrzebna synchronizacja w dostępie do pamięci

    • Przełączenie procesów jest względnie kosztowne

    • Wymagają względnie dużych zasobów

    Wątki

    • Mają dostęp do współdzielonych obszarów pamięci

    • Wymagana synchronizacja w dostępie do pamięci

    • Przełączanie wątków jest względnie tanie

    • Wymagają względnie niewielkich zasobów

  • 18

    Modele obliczeń równoległych. Systemy scentralizowane i rozproszone

    • Z punktu widzenia dostępnych metod/środków zrównoleglenia procesów można wyróżnić dwa podstawowe modele systemów: model systemów z pamięcią wspólną (systemy scentralizowane) oraz model z pamięcią lokalną (systemy rozproszone, sieciowe)

    • W przypadku systemów scentralizowanych procesy mają dostęp do wspólnego obszaru pamięci, a komunikacja najczęściej przybiera postać synchronizowanego odczytu/zapisu zmiennych globalnych (współdzielonych)

    • W przypadku systemów rozproszonych procesy mają dostęp wyłącznie do swojej pamięci lokalnej, a komunikacja odbywa się przez wymianę komunikatów lub zdalne wywoływanie procedur (RPC – Remote Procedure Call). W takim przypadku czas komunikacji jest zdecydowanie dłuższy niż w przypadku systemów scentralizowanych. Nakłada to na program rozproszony dodatkowe wymagania optymalizacji liczby operacji synchronizujących przebieg procesów

    • Powyższe modele wymagają różnych mechanizmów komunikacji, chociaż mechanizmy właściwe dla systemów rozproszonych mogą być wykorzystywane w systemach scentralizowanych

  • 19

    Przetwarzanie w środowiskach z pamięcią wspólną (1)

    • W systemach z pamięcią wspólną zasób pamięci jest współdzielony przez wszystkie procesory (w szczególności przez jeden procesor)

    • Konieczne jest zapewnienie ochrony pamięci wspólnej przez niepożądanymi interakcjami różnych procesów. Dlaczego?

    • Bezpieczeństwo zapewnia odpowiednia organizacja jednostek przetwarzania (procesy, wątki) w systemie operacyjnym oraz mechanizmy synchronizacji (kontroli dostępu do danych)

    • W systemach z pamięcią wspólną poszczególne zadania realizowane są przez procesy i wątki funkcjonujące w ramach jednego procesu

  • 20

    Przetwarzanie w środowiskach z pamięcią wspólną (2)

    • Wspólny segment danych wątków jednego procesu wykorzystywany jest do zapewnienia komunikacji (wymiany danych) pomiędzy wątkami

    • Gdy tworzony jest proces domyślnie tworzony jest wątek główny, z którego ciała możliwe jest utworzenie innych wątków. Proces kończy swoje działanie, gdy działanie kończy ostatni z jego wątków

    • Wątki są nazywane lekkimi procesami, ponieważ obciążają system w mniejszym stopniu niż procesy:

    • utworzenie wątku zajmuje mniej czasu niż utworzenie procesu

    • wątki są mniej pamięciożerne

    • przełączanie kontekstu wątku (zapis w TCB) zajmuje mniej czasu niż przełączanie procesora pomiędzy procesami (zapis w PCB)

  • 21

    Przetwarzanie w środowiskach z pamięcią wspólną (3)

    • Przełączanie kontekstu wymaga zapisu i odczytu danych z bloku kontrolnego procesu (Process Control Block – PCB)

    • PCB jest strukturą utrzymywaną w pamięci operacyjnej przez system operacyjny i stanowi reprezentację procesu

    • PCB zawiera m. in. następujące informacje

    • identyfikator procesu (Process ID – PID)

    • stan procesu (gotowy, zawieszony, oczekujący, …)

    • licznik instrukcji – wskaźnik do następnej instrukcji do wykonania

    • informacje przeznaczone dla schedulera: priorytet procesu, wykorzystany czas procesora, itd.

    • …

    • Przełączanie kontekstu zachodzi wyłącznie w systemach z wywłaszczaniem (z podziałem czasu).

  • 22

    Przetwarzanie w środowiskach z pamięcią lokalną (1)

    • Zgodnie z definicją systemy z pamięcią lokalną (systemy rozproszone, sieciowe) to systemy, w których wykonywane procesy posiadają własne, niezależne przestrzenie adresowe

    • W takich przypadkach nie istnieje pojęcie pamięci współdzielonej. Tym samym nie ma możliwości synchronizacji procesów za pomocą mechanizmów takich jak semafory, monitory, zamki, których celem jest ochrona zasobu pamięci przed niepożądanymi interakcjami różnych procesów

    • W systemach rozproszonych synchronizacja współpracujących lub konkurujących procesów jest realizowana przez mechanizm komunikatów lub zdalne wywoływanie procedur (RPC). Komunikaty mogą zawierać informacje sterujące, ale również dane (np. parametry, dane wejściowe do przetwarzania)

    • Programowanie dla systemów z pamięcią lokalną nazywane jest programowaniem rozproszonym

    • Pojęcie programowania rozproszonego nie ogranicza się wyłącznie do systemów, w których przestrzenie adresowe poszczególnych procesorów są fizycznie separowane. Programowanie rozproszone odnosi się również do programowania układów scentralizowanych, w których procesy z pewnych powodów nie wymieniają informacji za pomocą zmiennych współdzielonych

  • 23

    Przetwarzanie w środowiskach z pamięcią lokalną (2)

    • Wymiana komunikatów jest wspierana przez systemy operacyjne (potoki, łącza nazwane/nienazwane, gniazdka, itd.)

    • Ze względu na związki czasowe pomiędzy procesami wzajemnie się komunikującymi mechanizmy komunikacji można podzielić na

    • synchroniczne – wymiana informacji następuje w trakcie spotkania, tzn. proces wysyłający komunikat jest wstrzymywany tak długo, jak długo proces odbierający nie jest gotowy do odbioru komunikatu (i na odwrót)

    • asynchroniczne – spotkanie nie jest konieczne; wysłanie komunikatu może nastąpić w dowolnej chwili (gdy spełnione są pewne dodatkowe warunki, które nie obejmują jednak gotowości odbiorcy). Wykorzystywana jest w tym przypadku strona trzecia (pośrednicząca) w postaci np. bufora, kolejki buforującej

    • blokujące – wykonanie instrukcji następującej po instrukcji odbioru/wysłania danych jest możliwe dopiero po zakończeniu procesu odbioru/wysyłania

    • nieblokujące – przejście do kolejnej instrukcji następuje bez oczekiwania na zakończenie wysyłania/odbierania komunikatu

  • 24

    Przetwarzanie w środowiskach z pamięcią lokalną (3)

    • W modelu rozproszonym w zależności od sposobu współpracy procesów komunikaty mogą być przekazywane na różne sposoby:

    • komunikat przeznaczony dla konkretnego procesu

    • komunikat przeznaczony dla pierwszego odbiorcy (wysyłający nie musi wiedzieć, który proces konkretnie odbierze komunikat)

    • komunikat przeznaczony do wszystkich (broadcast)

    • Komunikaty są wykorzystywane do bezpośredniego przekazywania danych pomiędzy procesami i/lub do jawnej synchronizacji. Synchronizacja może być realizowana np. w modelu z pojedynczym tokenem. W takim przypadku wykonanie pewnych operacji (sekcja krytyczna, bufor) jest możliwe przez ten proces, który jest aktualnie w posiadaniu tokenu

    • Problemy komunikacji: zaginięcie komunikatu od serwera, zaginięcie odpowiedzi od serwera, awaria klienta/serwera po wysłaniu/otrzymaniu zamówienia

  • 25

    Synchronizacja i komunikacja pomiędzy procesami i wątkami

    • Komunikacja – przesyłanie komunikatów (tokenów?) pomiędzy współpracującymi/współzawodniczącymi wątkami lub procesami. Komunikacja synchroniczna i asynchroniczna.

    • Synchronizacja – zapewnienie pożądanych zależności czasowych wykonujących się procesów lub wątków. Komunikacja jest formą synchronizacji.

    Kiedy synchronizacja jest niezbędna?

    • Gdy procesy współdzielą wspólne struktury danych (np. zmienne globalne) lub współzawodniczą w dostępnie do wspólnego zasobu/struktury. Dlaczego synchronizacja jest w takich przypadkach konieczna?

    • Pewne procesy dostarczają dane dla innych procesów.

    Uwaga 1: Programowanie współbieżne obejmuje również (właściwie przede wszystkim) zaprojektowanie i implementację komunikacji i/lub synchronizacji procesów lub wątków

    Uwaga 2: W ogólności programista nie może zakładać określonej kolejności wykonania się procesów/wątków. Należy zakładać losowość lub określić kolejność

  • 26

    Wzajemne wykluczanie (1)

    • Jedną z metod synchronizacji procesów w systemach scentralizowanych jest wzajemne wykluczanie (mutual exclusion – mutex)

    • Sekcja krytyczna – fragment kodu (fragment procesu) , w którym następuje korzystanie z zasobu współdzielonego (fragment wykonywany w sposób wyłączny)

    • Zasób współdzielony – zasób, który może być w sposób wyłączny wykorzystywany przez wiele współzawodniczących procesów (w danej chwili z zasobu może korzystać jeden lub ograniczona liczba wątków/procesów)

    •Problem: należy zapewnić, by w danej chwili z zasobu mógł korzystać tylko jeden proces (lub ograniczona od góry ich liczba), a pozostałe, które chcą uzyskać do niego dostęp powinny czekać na jego zwolnienie. Równoważnie: wykonanie sekcji krytycznej jednego procesu nie może przeplatać się z wykonaniem sekcji krytycznej dowolnego innego procesu

    • Wzajemne wykluczanie stanowi abstrakcję problemu przydziału dostępu do zasobu współdzielonego (np. kanału komunikacyjnego, pamięci). Problem pojawia się gdy liczba chętnych do skorzystania z zasobu przekracza liczbę obiektów, które z zasobu mogą korzystać

  • 27

    Wzajemne wykluczanie (2)

    • Problem oczekiwania aktywnego i pasywnego

    • Warunki poprawnego rozwiązania problemu wzajemnego wykluczania:

    1. W danym punkcie czasu tylko jeden proces może być w trakcie wykonywania sekcji krytycznej (sekcje krytyczne różnych procesów nie mogą być przeplatane)

    2. Nie wolno dokonywać jakichkolwiek założeń dotyczących względnych lub bezwzględnych szybkości wykonywania procesów

    3. Proces nie może wykonywać swojej sekcji krytycznej nieskończenie długo (powinien wykonywać ją tak krótko jak to możliwe; patrz transakcje w DBMS)

    4. W procesie nie może wystąpić nieobsłużony błąd w trakcie wykonywania sekcji krytycznej

    5. Zachowanie procesów poza sekcją krytyczną nie może być w jakikolwiek sposób ograniczane (procesy powinny być luźno powiązane)

    6. Wybór procesu wchodzącego do sekcji krytycznej powinien odbywać się w skończonym czasie

    7. Proces nie może być wywłaszczany z przyznanego zasobu współdzielonego

    8. Procesy nie mogą mieć przypisanych żadnych statycznych priorytetów

  • 28

    Wzajemne wykluczanie (3)

    • Wzajemne wykluczanie realizuje się przez wykorzystanie instrukcji specjalnych przed wejściem do sekcji krytycznej i po wyjściu z niej (protokoły wstępny i końcowy)

    • Przykład:while true

    begin

    przetwarzanie lokalne

    protokół wstępny

    strefa krytyczna

    protokół końcowy

    end

    • Sekcja krytyczna jest otoczona specjalnymi blokami kodu

    • Sekcje lokalne mogą być wykonywane współbieżnie przez wiele różnych procesów

    • Warunek bezpieczeństwa jest realizowany przez zagwarantowanie, że dwa procesy/wątki nigdy nie znajdą się współbieżnie w swoich sekcjach krytycznych

    • Wzajemne wykluczanie jest wymagane zarówno w systemach scentralizowanych jak i rozproszonych. Realizuje się je różnymi metodami (np. muteksy - w systemach scentralizowanych, tokeny - w systemach rozproszonych)

  • 29

    Poprawność programów sekwencyjnych

    W przypadku programów sekwencyjnych definicja poprawności wymaga spełnienia dwóch warunków: warunku stopu oraz tego, że dla dowolnych poprawnych danych wejściowych program/algorytm po zatrzymaniu da poprawne wyniki

    Poprawność programów współbieżnych

    Istnieją dwa warunki poprawności programów współbieżnych

    • Bezpieczeństwo – niedopuszczalność do sytuacji niepożądanej (wykluczenie stanu niepożądanego; wykluczenie niepożądanych przeplotów)

    • Żywotność – każdy proces w końcu wykona swoją pracę (w szczególności: otrzyma dostęp do współdzielonego zasobu)

    Przejawy braku żywotności

    • Zakleszczenie (deadlock) – globalny brak żywotności; dotyczy blokady całego systemu współbieżnego (zakleszczają się co najmniej dwa procesy/wątki). Jest łatwiejsze do wykrycia (ze względu na swój globalny charakter)

    • Zagłodzenie (wykluczenie, lockout, starvation) – lokalny brak żywotności. W jakich warunkach może dojść do zagłodzenia i jak eliminować takie warunki?

  • 30

    Poprawność programów współbieżnych

    •W ogólności klasyczne testowanie programów nie daje dowodu na to, że dany program współbieżny jest poprawny

    •Program współbieżny jest poprawny pod warunkiem jednoczesnego spełnienia obu warunków poprawności. Spełnienie jednego z warunków nie daje poprawnego rozwiązania

    • Przykład: program współbieżny, w którym co najmniej jeden z procesów nie uzyska dostępu do zasobu współdzielonego może spełniać warunek bezpieczeństwa, ale nie jest to program poprawny, ponieważ nie spełnia warunku żywotności (zagłodzenie)

  • 31

    Zagłodzenie procesów

    • Zagłodzenie procesu to stan programu współbieżnego, w którym dany proces jest wstrzymywany pomimo spełnienia warunków wznowienia

    • Przykład 1: do zagłodzenia może dojść w sytuacji, gdy decyzja o przyznaniu zasobów jest oparta na priorytecie danego procesu oraz w puli procesów oczekujących na wznowienie zawsze istnieje proces o niższym priorytecie niż pozostałe. W takim przypadku prawdopodobieństwo zagłodzenia procesu zwiększa się wraz ze wzrostem częstotliwości zgłaszania żądań dostępu do zasobu

    • Przykład 2: do zagłodzenia może dojść w przypadku losowego rozstrzygania o przyznaniu zasobów dla danego procesu. Przykład: Niech program współbieżny składa się z 3 procesów współzawodniczących o dostęp do zasobu współdzielonego1. P1 uzyskuje dostęp do zasobu

    2. P2 i P3 zgłaszają żądanie dostępu do zasobu

    3. P1 zwalnia zasób, P2 i P3 konkurują

    4. P2 wygrywa rywalizację i otrzymuje zasób, P3 oczekuje

    5. P1 zgłasza żądanie dostępu do zasobu

    6. P2 zwalnia zasób, P1 i P3 konkurują

    7. P1 wygrywa rywalizację i otrzymuje zasób, P3 oczekuje

    8. P2 zgłasza żądanie dostępu do zasobu

    9. P1 zwalnia zasób, P2 i P3 konkurują

    10. P2 wygrywa rywalizację i otrzymuje zasób, P3 oczekuje, …

  • 32

    Zakleszczenie

    1 2

    3 4

  • 33

    Zakleszczenie. Warunki konieczne (niewystarczające)

    • Wzajemne wykluczanie – istnieje co najmniej jeden zasób, który w danym czasie może być wykorzystywany tylko przez jeden proces

    • Brak wywłaszczania – zasoby nie podlegają wywłaszczeniu, tzn. zasób nie może zostać odebrany zajmującemu go procesowi podczas wykorzystania zasobu

    • Przetrzymywanie zasobu i oczekiwanie na inny

    • Cykl w grafie oczekiwania na zasoby – istnieje zamknięty łańcuch procesów (cykl), w którym każdy proces oczekuje na zasoby przetrzymywane przez proces poprzedzający, np. P1 zajmuje Z1, P2 zajmuje Z2, P1 oczekuje na Z2, P2 oczekuje na Z1

    Uwaga: powyższe 4 warunki nie są niezależne

  • 34

    Strategie obsługi zakleszczeń (1)

    • Zapobieganie (preventing) – zapewnienie, że co najmniej jeden z powyższych warunków koniecznych jest niespełniony

    1. Wzajemne wykluczanie – rezygnacja z tego warunku w praktyce nie jest możliwa. Jest to jeden z podstawowych warunków poprawnego działania systemów współbieżnych

    2. Brak wywłaszczania - wprowadzanie możliwości wywłaszczania, np. poprzez odbieranie udostępnionych zasobów procesowi, który żąda dostępu do zasobu zajętego przez inny proces.

    Problemy:

    • Niskie wykorzystanie zasobów i ryzyko zagłodzenia procesów wykorzystujących dużą liczbę zasobów (małe prawdopodobieństwo skompletowania zestawu wymaganych zasobów).

    • Narzut czasowy: wywłaszczenie procesu jest równoważne wycofaniu wszystkich operacji wykonanych dotychczas przez proces w sekcji krytycznej – sekcja krytyczna jest traktowana jak operacja atomowa (wszystko albo nic) – i przywrócenie stanu sprzed rozpoczęcia sekcji. Niepożądane szczególnie w przypadku systemów z dużym prawdopodobieństwem wystąpienia zakleszczenia

  • 35

    Strategie obsługi zakleszczeń (2)

    3. Cykl w grafie oczekiwania na zasoby – zanegowanie istnienia tego warunku wymaga takiego zarządzania przydziałem zasobów, by nie powstał cykl w grafie przydziału. Klasycznym rozwiązaniem jest algorytm Havendera, w którym każdy zasób posiada swój unikalny identyfikator liczbowy. Przydział zasobów danemu procesowi realizowany jest tak by numery zasobów tworzyły ciąg monotoniczny. Rozwiązanie wpływa na sposób zamawiania zasobów

    4. Przetrzymywanie zasobu i oczekiwanie na inny - rezygnacja z przetrzymywania i oczekiwania na inny zasób może się sprowadzać do wymagania by proces otrzymywał komplet wymaganych zasobów (wszystko albo nic: proces otrzymuje komplet zasobów lub nie otrzymuje żadnego).

    Prowadzi to do problemów jak w punkcie wyżej. Biblioteki programistyczne udostępniają metody (np. trylock()), które gwarantują niedopuszczalność sytuacji zajęcia jednego zasobu i oczekiwania na inny. W takich przypadkach zasób jest zajmowany wyłącznie, gdy jest wolny. W takim przypadku wejście do sekcji krytycznej jest możliwe tylko wówczas, gdy wszystkie zasoby, które będą wykorzystywane w sekcji krytycznej są wolne. Rozwiązanie wpływa na sposób zamawiania zasobów

  • 36

    Strategie obsługi zakleszczeń (3)

    • Unikanie (avoiding) - niedopuszczanie do sytuacji zakleszczenia poprzez proaktywne (z wyprzedzeniem) badanie żądań dostępu do zasobów. System może nie dopuścić do zakleszczenie przez badania aktualnie dostępnych zasobów, zasobów aktualnie przydzielonych do procesów oraz przyszłych żądań oraz zwolnień zasobów

    • Wykrywanie i likwidacja. W przypadku, gdy system nie korzysta ani z algorytmu zapobiegania zakleszczeniom, ani z algorytmu ich unikania, to zakleszczenie może się pojawić. Wykrywanie i likwidacja zakleszczeń polega na cyklicznym monitorowaniu stanu systemu pod kątem istnienia zakleszczenia (np. cykl w grafie oczekiwania). Po zidentyfikowaniu zakleszczenia uruchamiany jest algorytm likwidacji zakleszczenia sprowadzający się do wywłaszczania kolejnych procesów aż do momentu, gdy zakleszczenie zostanie zlikwidowane. Procesy wywłaszczone nazywane są ofiarami zakleszczenia. Wskazanie ofiar pozwala funkcjonować pozostałym procesom systemu. Strategia wykrywania i likwidacji wiąże się z narzutem czasowym wynikającym m. in. z: czasu wykonania algorytmu wykrycia i likwidacji, interwału czasu pomiędzy wystąpieniem stanu zakleszczenia do momentu jego wykrycia.

  • 37

    Szeregowanie wątków lub procesów

    • Procedury systemu operacyjnego (scheduler, dispatcher, planista) odpowiadają za szeregowanie wątków lub procesów do wykonania. Wybór dokonywany jest z puli wątków gotowych do wykonania (inne możliwe stany wątków: nowy, aktywny, gotowy do wykonania, czekający, zakończony)

    • Procedury szeregujące mogą stosować różne strategie szeregowania i uwzględniać różne atrybuty wątków (priorytet, stan wątku, kolejność zgłaszania żądania dostępu do zasobu, szacowanego czasu do zakończenia wykonywania, etc.)

    • Zadaniem schedulera jest zapewnienie optymalnego wykorzystania zasobów w systemach wielowątkowych (wieloprogramowych)

    • Możliwe jest planowanie z wywłaszczaniem i bez wywłaszczania

    • Planowanie bez wywłaszczania – po przejściu wątku do stanu aktywnego planista pozostaje bezczynny aż do zakończenia fazy wykonywania wątku

    • Planowanie wywłaszczaniem – po przejściu wątku do stanu aktywnego wątkowi mogą być odebrane zasoby po zajściu odpowiedniego zdarzenia w systemie. Wówczas zasób oddawany jest innemu wątkowi z puli wątków gotowych do wykonania

    • Strategie planowania: FCFS, SJF, priorytetowe, etc.

  • 38

    Synchronizacja niskopoziomowa. Algorytm Dekkera (1)

    • Algorytm Dekkera jest algorytmem synchronizacji dwóch procesów/wątków współbieżnych bez konieczności odwoływania się do gotowych narzędzi synchronizacyjnych

    • Algorytm Dekkera sprowadza się do odpowiedniego zakodowania sekcji wejściowej i wyjściowej chroniących sekcję krytyczną

    • Przy założeniu dwóch procesów wymaga 3 zmiennych współdzielonych

    - czyja_kolej = {1,2}. Zmienna pełni rolę arbitra rozstrzygającego, który proces może wejść do sekcji krytycznej. Ustawienie inicjalne wartości zmiennej łamie symetrię pomiędzy procesami/wątkami i określa kolejność w jakiej będą one wykonywane

    - dwuelementowa tablica flag k. Każdy z procesów ma dostęp do jednego pola tablicy. Pole jest ustawiane na true, gdy dany proces chce wejść do sekcji krytycznej. Inicjalnie flagi ustawione są na false

    • Każdy z procesów posiada swój identyfikator (np. identyfikator liczbowy)

  • 39

    Synchronizacja niskopoziomowa. Algorytm Dekkera (2)

    • protokół wejściowy. P jest identyfikatorem procesu; przyjmuje wartości 1 lub 2

    • protokół wyjściowy

  • 40

    Synchronizacja niskopoziomowa. Algorytm Dekkera (3)

    • Podana wersja algorytmu jest poprawna dla dwóch procesów/wątków. Algorytm można uogólnić do N procesów/wątków i wówczas wymaga 2N-1 zmiennych. Liczba procesów/wątków musi być znana z góry (niepraktyczne!)

    • Poważnym problemem jest aktywne czekanie (busy waiting; proces oczekuje na udostępnienie zasobu wykonując pętlę sprawdzającą jego dostępność).

    • Dlaczego aktywne czekanie jest problemem? Ponieważ proces oczekujący na wejście do swojej sekcji krytycznej jest wykonywany pożytkując czas procesora na wykonywanie pustych przebiegów pętli

    • W ogólności mechanizm aktywnego czekania powinien być eliminowany z rozwiązań współbieżnych. Aktywne czekanie można zastąpić mechanizmem wstrzymywania wątków/procesów

    • Czy w przypadku, gdy tylko jeden proces chce korzystać z sekcji krytycznej uzyskuje dostęp bez ograniczeń?

    • Procesy korzystają z sekcji krytycznej naprzemiennie (wymuszone przez ustawianie zmiennej czyja_kolej). W przypadku, gdy jeden z procesów przerwie swoje działanie z błędem drugi z procesów jest blokowany

  • 41

    Algorytm Petersona. Podejście 1

    • Rozpatrzmy poniższy sposób synchronizacji za pomocą jednej zmiennej globalnej. Niech zmienna czyja_kolej jest inicjalnie ustawiona na wartość 1. Przykład:

    • Pytanie: co dzieje się w sytuacji, gdy tylko jeden proces chce wchodzić do sekcji krytycznej?

    • Można pokazać, że taki sposób rozwiązania posiada własność bezpieczeństwa, tzn. tylko jeden proces w danym momencie może przebywać w sekcji krytycznej

    • Problem faworyzacji procesu na który wskazuje inicjalna wartość zmiennej czyja_kolej. Na czym polega faworyzowanie procesu?

  • 42

    Algorytm Petersona. Podejście 1 c.d.

    • Algorytm nie spełnia warunku żywotności. Dany proces, teoretycznie, może dowolnie długo wykonywać swoją sekcję lokalną - w szczególności nieskończenie długo. W takim przypadku drugi z procesów nie wejdzie do sekcji krytycznej –zostanie zagłodzony. Wynika to z naprzemienności wykonywania procesów

    • Procesy są ściśle ze sobą powiązane: wykonują się w sekwencji 1,2,1,2,1,2, etc. Jako pierwszy wykona się zawsze wątek/proces wskazywany przez inicjalne ustawienie zmiennej czyja_kolej.

    • Nie jest możliwe wykonanie procesów w sekwencji …,1, 1, …. lub …, 2, 2, …

    • Powyższe jest problemem szczególnie w sytuacji, gdy czas wykonania sekcji lokalnych dwóch procesów znacznie się różni. W takiej sytuacji proces szybszy jest spowalniany przez proces wolniejszy (czeka na zakończenie jego pracy)

    • Problem pojawia się w przypadku scenariusza, w którym tylko jeden z procesów chce uzyskiwać dostęp do sekcji krytycznej

  • 43

    Algorytm Petersona. Podejście 2

    • Rozpatrzmy próbę synchronizacji przy wykorzystaniu dwóch zmiennych logicznych (np. tablica o dwóch elementach), gdzie każdy z wątków/procesów ustawia odpowiednie pole tablicy na wartość true w przypadku, gdy jest w sekcji krytycznej. Inicjalnie obie zmienne (pola tablicy) są ustawione na false.

    • W tym przypadku wątki/procesy nie są ze sobą ściśle powiązane, tzn. nie muszą się wykonywać w sekwencji - wątek który nie chce lub nie może wejść do sekcji nie blokuje drugiego z wątków

    • Problem: występuje złamanie warunku bezpieczeństwa w danej chwili do sekcji krytycznej mogą wejść oba wątki

  • 44

    Algorytm Petersona. Podejście 2 c.d.

    • Przykład przeplotu obu wątków prowadzący do naruszenia warunku bezpieczeństwa algorytmu:

    • Wniosek: nie jest to poprawny algorytm synchronizacyjny ponieważ do sekcji krytycznej mogą wejść oba procesy nie spełnia warunku bezpieczeństwa

  • 45

    Algorytm Petersona. Podejście 3

    • W miejsce zmiennych logicznych reprezentujących fakt obecności (wejścia) wątku/procesu do sekcji wprowadźmy zmienne logiczne reprezentujące chęć wejścia wątku/procesu do sekcji krytycznej. Obie zmienne inicjalnie są ustawione na wartość false. Przykład:

    • Wątek, który jako jedyny chce wykonywać sekcję krytyczną może tego dokonywać bez przeszkód (wątki nie są ze sobą powiązane)

    • Algorytm daje program bezpieczny (spełniony jest warunek bezpieczeństwa)

    • Algorytm narusza warunek żywotności prowadzi do zakleszczeń

  • 46

    Algorytm Petersona. Podejście 3 c.d.

    • Przykład przeplotu prowadzącego do zakleszczenia

    • W przypadku powyższego przeplotu nigdy nie zostanie zrealizowany warunek wyjścia z pętli aktywnego czekania procesów 1 i 2. Zakleszczenie

    • Wniosek: nie jest to poprawny algorytm synchronizacyjny nie spełnia warunku żywotności

  • 47

    Algorytm Petersona. Ostateczna postać

    • Algorytm Petersona

    • Algorytm gwarantuje bezpieczeństwo i żywotność

    • Algorytm posiada wszystkie wady algorytmu Dekkera: wymaga aktywnego czekania oraz chociaż można go uogólnić na dowolne N wątków/procesów, to wymaga w takim przypadku 2N-1 zmiennych, gdzie N musi być znane a priori

  • 48

    Algorytm Petersona. Ostateczna postać c.d.

    • Przeanalizujmy przykład

    • Wszystko jest OK.