Współbieżność a równoległość
Zarówno współbieżność, jak i równoległość są używane w odniesieniu do programów wielowątkowych, ale istnieje wiele nieporozumień dotyczących podobieństwa i różnicy między nimi. Najważniejsze pytanie w tym zakresie: czy równoległość współbieżności jest czy nie? Chociaż oba terminy wydają się dość podobne, ale odpowiedź na powyższe pytanie brzmi NIE, współbieżność i równoległość nie są tym samym. A jeśli nie są takie same, jaka jest między nimi podstawowa różnica?
Mówiąc prościej, współbieżność zajmuje się zarządzaniem dostępem do współdzielonego stanu z różnych wątków, a z drugiej strony równoległość polega na wykorzystaniu wielu procesorów lub ich rdzeni w celu poprawy wydajności sprzętu.
Szczegóły współbieżności
Współbieżność występuje, gdy dwa zadania nakładają się na siebie podczas wykonywania. Może to być sytuacja, w której aplikacja obsługuje więcej niż jedno zadanie w tym samym czasie. Możemy to zrozumieć schematycznie; w tym samym czasie postępuje wiele zadań, jak następuje -
Poziomy współbieżności
W tej sekcji omówimy trzy ważne poziomy współbieżności w zakresie programowania -
Współbieżność niskiego poziomu
Na tym poziomie współbieżności istnieje jawne użycie operacji atomowych. Nie możemy używać tego rodzaju współbieżności do budowania aplikacji, ponieważ jest ona bardzo podatna na błędy i trudna do debugowania. Nawet Python nie obsługuje tego rodzaju współbieżności.
Współbieżność średniego poziomu
W tej współbieżności nie ma użycia jawnych operacji atomowych. Używa jawnych blokad. Python i inne języki programowania obsługują tego rodzaju współbieżność. Przeważnie programiści aplikacji używają tej współbieżności.
Współbieżność wysokiego poziomu
W tej współbieżności nie są używane ani jawne operacje niepodzielne, ani jawne blokady. Python maconcurrent.futures moduł do obsługi tego rodzaju współbieżności.
Właściwości systemów współbieżnych
Aby program lub system współbieżny były poprawne, muszą spełniać pewne właściwości. Właściwości związane z zakończeniem systemu są następujące -
Właściwość poprawności
Właściwość poprawności oznacza, że program lub system musi podać żądaną poprawną odpowiedź. Aby to uprościć, możemy powiedzieć, że system musi poprawnie odwzorować stan programu początkowego na stan końcowy.
Majątek bezpieczeństwa
Właściwość bezpieczeństwa oznacza, że program lub system musi pozostać w pliku “good” lub “safe” stan i nigdy nic nie robi “bad”.
Majątek życia
Ta właściwość oznacza, że program lub system musi “make progress” i osiągnie jakiś pożądany stan.
Aktorzy systemów współbieżnych
Jest to wspólna właściwość systemu współbieżnego, w którym może istnieć wiele procesów i wątków, które działają w tym samym czasie, aby wykonywać postępy w wykonywaniu własnych zadań. Te procesy i wątki nazywane są aktorami systemu współbieżnego.
Zasoby systemów współbieżnych
Aktorzy muszą wykorzystywać zasoby, takie jak pamięć, dysk, drukarka itp., Aby wykonywać swoje zadania.
Pewien zbiór zasad
Każdy współbieżny system musi posiadać zestaw reguł określających rodzaj zadań do wykonania przez aktorów i ich harmonogram. Zadania mogą obejmować pozyskiwanie blokad, udostępnianie pamięci, modyfikowanie stanu itp.
Bariery współbieżnych systemów
Wdrażając systemy współbieżne, programista musi wziąć pod uwagę dwa ważne zagadnienia, które mogą stanowić bariery systemów współbieżnych -Udostępnianie danych
Istotną kwestią podczas wdrażania systemów współbieżnych jest współdzielenie danych pomiędzy wieloma wątkami lub procesami. W rzeczywistości programista musi zapewnić, że blokady chronią współdzielone dane, tak aby wszystkie dostępy do nich były serializowane i tylko jeden wątek lub proces miał dostęp do współdzielonych danych w danym momencie. W przypadku, gdy wiele wątków lub procesów próbuje uzyskać dostęp do tych samych udostępnionych danych, nie wszystkie, z wyjątkiem co najmniej jednego, zostaną zablokowane i pozostaną bezczynne. Innymi słowy, możemy powiedzieć, że bylibyśmy w stanie używać tylko jednego procesu lub wątku w czasie, gdy obowiązuje blokada. Istnieje kilka prostych rozwiązań w celu usunięcia wyżej wymienionych barier -
Ograniczenie udostępniania danych
Najprostszym rozwiązaniem jest nieudostępnianie żadnych zmiennych danych. W takim przypadku nie musimy używać jawnego blokowania, a bariera współbieżności spowodowana wzajemnymi danymi zostałaby rozwiązana.
Pomoc w zakresie struktury danych
Często współbieżne procesy muszą mieć dostęp do tych samych danych w tym samym czasie. Innym rozwiązaniem, niż użycie jawnych blokad, jest użycie struktury danych, która obsługuje współbieżny dostęp. Na przykład możemy użyćqueuemoduł, który zapewnia kolejki bezpieczne dla wątków. Możemy również użyćmultiprocessing.JoinableQueue klasy dla współbieżności opartej na wieloprocesowości.
Niezmienny transfer danych
Czasami struktura danych, której używamy, powiedzmy kolejka współbieżności, nie jest odpowiednia, wtedy możemy przekazać niezmienne dane bez ich blokowania.
Zmienny transfer danych
Kontynuując powyższe rozwiązanie, załóżmy, że jeśli wymagane jest przekazywanie tylko danych podlegających zmianom, a nie danych niezmiennych, to możemy przekazywać zmienne dane, które są tylko do odczytu.
Udostępnianie zasobów we / wy
Inną ważną kwestią we wdrażaniu systemów współbieżnych jest wykorzystanie zasobów we / wy przez wątki lub procesy. Problem pojawia się, gdy jeden wątek lub proces używa wejścia / wyjścia przez tak długi czas, a inny jest bezczynny. Tego rodzaju barierę widzimy pracując z aplikacją wymagającą dużej liczby wejść / wyjść. Można to zrozumieć na przykładzie żądania stron z przeglądarki internetowej. To ciężka aplikacja. Tutaj, jeśli szybkość, z jaką żądane są dane, jest wolniejsza niż szybkość, z jaką są one zużywane, to mamy barierę we / wy w naszym współbieżnym systemie.
Poniższy skrypt Pythona służy do żądania strony internetowej i uzyskania czasu, jaki zajęło naszej sieci uzyskanie żądanej strony -
import urllib.request
import time
ts = time.time()
req = urllib.request.urlopen('http://www.tutorialspoint.com')
pageHtml = req.read()
te = time.time()
print("Page Fetching Time : {} Seconds".format (te-ts))
Po wykonaniu powyższego skryptu możemy uzyskać czas pobierania strony, jak pokazano poniżej.
Wynik
Page Fetching Time: 1.0991398811340332 Seconds
Widzimy, że czas na pobranie strony jest dłuższy niż jedna sekunda. A co, jeśli chcemy pobrać tysiące różnych stron internetowych, możesz zrozumieć, ile czasu zajmie nasza sieć.
Co to jest równoległość?
Równoległość można zdefiniować jako sztukę dzielenia zadań na podzadania, które mogą być przetwarzane jednocześnie. Jest to przeciwieństwo współbieżności, jak omówiono powyżej, w której dwa lub więcej zdarzeń zachodzi w tym samym czasie. Możemy to zrozumieć schematycznie; zadanie jest podzielone na kilka podzadań, które mogą być przetwarzane równolegle, w następujący sposób -
Aby uzyskać więcej informacji na temat różnicy między współbieżnością a równoległością, rozważ następujące punkty -
Współbieżne, ale nie równoległe
Aplikacja może być współbieżna, ale nie równoległa, co oznacza, że w tym samym czasie przetwarza więcej niż jedno zadanie, ale zadania nie są dzielone na podzadania.
Równolegle, ale nie równolegle
Aplikacja może być równoległa, ale nie współbieżna, co oznacza, że działa tylko na jednym zadaniu na raz, a zadania podzielone na podzadania mogą być przetwarzane równolegle.
Ani równoległe, ani współbieżne
Aplikacja nie może być ani równoległa, ani współbieżna. Oznacza to, że działa tylko na jednym zadaniu naraz, a zadanie nigdy nie jest dzielone na podzadania.
Zarówno równoległe, jak i współbieżne
Aplikacja może być zarówno równoległa, jak i współbieżna, co oznacza, że działa jednocześnie na wielu zadaniach, a zadanie jest podzielone na podzadania do wykonywania ich równolegle.
Konieczność równoległości
Możemy osiągnąć paralelizm, rozdzielając podzadania na różne rdzenie pojedynczego procesora lub na wiele komputerów połączonych w sieci.
Rozważ następujące ważne punkty, aby zrozumieć, dlaczego konieczne jest osiągnięcie równoległości:
Wydajne wykonanie kodu
Za pomocą równoległości możemy wydajnie uruchamiać nasz kod. Zaoszczędzi to nasz czas, ponieważ ten sam kod w częściach działa równolegle.
Szybszy niż przetwarzanie sekwencyjne
Obliczenia sekwencyjne są ograniczone czynnikami fizycznymi i praktycznymi, przez co nie jest możliwe uzyskanie szybszych wyników obliczeń. Z drugiej strony ten problem jest rozwiązany przez obliczenia równoległe i daje nam szybsze wyniki obliczeń niż obliczenia sekwencyjne.
Krótszy czas realizacji
Przetwarzanie równoległe skraca czas wykonywania kodu programu.
Jeśli mówimy o prawdziwym przykładzie równoległości, karta graficzna naszego komputera jest przykładem, który podkreśla prawdziwą moc przetwarzania równoległego, ponieważ ma setki indywidualnych rdzeni przetwarzających, które działają niezależnie i mogą wykonywać operacje w tym samym czasie. Z tego powodu jesteśmy w stanie uruchamiać również aplikacje i gry z najwyższej półki.
Zrozumienie procesorów do wdrożenia
Wiemy o współbieżności, równoległości i różnicy między nimi, ale co z systemem, w którym ma być zaimplementowana. Niezbędna jest znajomość systemu, na którym będziemy wdrażać, ponieważ daje nam to możliwość podejmowania świadomych decyzji podczas projektowania oprogramowania. Mamy dwa rodzaje procesorów -
Procesory jednordzeniowe
Procesory jednordzeniowe mogą w dowolnym momencie wykonywać jeden wątek. Te procesory używającontext switchingaby przechowywać wszystkie niezbędne informacje dotyczące wątku w określonym czasie, a następnie przywrócić je później. Mechanizm przełączania kontekstów pomaga nam robić postępy w wielu wątkach w ciągu danej sekundy i wygląda na to, że system pracuje nad wieloma rzeczami.
Procesory jednordzeniowe mają wiele zalet. Te procesory wymagają mniej energii i nie ma złożonego protokołu komunikacyjnego między wieloma rdzeniami. Z drugiej strony szybkość procesorów jednordzeniowych jest ograniczona i nie nadaje się do większych aplikacji.
Procesory wielordzeniowe
Procesory wielordzeniowe mają wiele niezależnych jednostek przetwarzających zwanych również cores.
Takie procesory nie potrzebują mechanizmu przełączania kontekstu, ponieważ każdy rdzeń zawiera wszystko, czego potrzebuje do wykonania sekwencji zapisanych instrukcji.
Cykl pobierania, dekodowania i wykonywania
Rdzenie procesorów wielordzeniowych wykonują cykl. Ten cykl nazywa sięFetch-Decode-Executecykl. Obejmuje następujące kroki -
Sprowadzać
Jest to pierwszy krok cyklu, który polega na pobieraniu instrukcji z pamięci programu.
Rozszyfrować
Niedawno pobrane instrukcje byłyby konwertowane na serię sygnałów, które będą wyzwalać inne części procesora.
Wykonać
Jest to ostatni krok, w którym zostaną wykonane pobrane i zdekodowane instrukcje. Wynik wykonania zostanie zapisany w rejestrze procesora.
Jedną z zalet jest to, że wykonanie w procesorach wielordzeniowych jest szybsze niż w procesorach jednordzeniowych. Nadaje się do większych zastosowań. Z drugiej strony problemem jest złożony protokół komunikacyjny między wieloma rdzeniami. Wiele rdzeni wymaga więcej mocy niż procesory jednordzeniowe.