Różnica między programowaniem równoległym i równoległym?

44

Patrząc na programowanie współbieżne, powszechnie stosuje się dwa terminy, tj. Współbieżny i równoległy.

Niektóre języki programowania w szczególności twierdzą, że obsługują programowanie równoległe, takie jak Java .

Czy to oznacza, że ​​programowanie równoległe i współbieżne faktycznie się różni?

nish1013
źródło
10
Tak, programowanie współbieżne i równoległe jest różne. na przykład możesz mieć dwa wątki (lub procesy) działające jednocześnie na tym samym rdzeniu poprzez przełączanie kontekstu. Kiedy dwa wątki (lub procesy) są wykonywane na dwóch różnych rdzeniach (lub procesorach), masz równoległość. Tak więc w pierwszym przypadku (współbieżność) paralelizm jest tylko „wirtualny”, podczas gdy w drugim przypadku masz prawdziwy paralelizm. Dlatego każdy program równoległy jest współbieżny, ale odwrotność niekoniecznie jest prawdą.
Massimo Cafaro
1
Uważaj tutaj. Możesz osiągnąć ten sam wynik albo przez obsługę języka (tj. Rozszerzenie języka o nowe konstrukcje) lub przez zastosowanie podejścia niskiego poziomu (np. Przez użycie biblioteki, tak jak w przypadku MPI i OpenMP). W każdym razie, przy obecnych procesorach wielordzeniowych i systemach operacyjnych ze wsparciem SMP, program, który będzie współbieżny, jeśli zostanie uruchomiony na starych procesorach jednordzeniowych, może być wykonywany równolegle, jeśli system operacyjny planuje wątki wykonania programu na różnych rdzeniach. Tak więc rozróżnienie jest obecnie trochę „rozmyte”.
Massimo Cafaro
3
To, czego używasz dla prędkości stałej opóźnienia światła. Współbieżnie udajesz, że opóźnienie światła wynosi jeden cykl zegara. Równolegle zakładasz, że jeden serwer jest obok, w rozproszonym zakładasz, że jeden serwer jest na Marsie.
1
Robert Harper omawia ten problem w dwóch postach na blogu: „Równoległość nie jest współbieżnością” oraz „Równoległość i współbieżność, ponownie odwiedzone” , które warto sprawdzić.
Basil

Odpowiedzi:

26

Odróżnij paralelizm (wykorzystanie dodatkowych jednostek obliczeniowych, aby wykonać więcej pracy na jednostkę czasu) od współbieżności (zarządzanie dostępem do zasobów współdzielonych). Naucz najpierw paralelizmu, ponieważ jest łatwiejszy i pomaga ustalić niesekwencyjny sposób myślenia.

Z „A Sophomoric ∗ Wprowadzenie do paralelizmu i współbieżności pamięci współużytkowanej” autorstwa Dana Grossmana (wersja z 16 listopada 2013 r.)

Raphael
źródło
21

Oprócz odpowiedzi Nisha, polecam książkę Simona Marlowa o programowaniu równoległym i współbieżnym w Haskell lub jego krótszy samouczek . Odpowiadają na twoje pierwsze pytanie z perspektywy Haskella, dzięki czemu mogą lepiej pasować do teoretycznie skłonnych czytelników (Haskell jest czysto funkcjonalnym, leniwym językiem programowania, który jest bliższy matematyce niż innym językom).

Cytując stamtąd:

W wielu dziedzinach słowa równoległe i współbieżne są synonimami; nie w programowaniu, gdzie są one używane do opisania zasadniczo różnych pojęć.

Program równoległy to taki, który wykorzystuje wiele sprzętów obliczeniowych (np. Wiele rdzeni procesorów) w celu szybszego wykonywania obliczeń. Różne części obliczeń są delegowane do różnych procesorów wykonujących się w tym samym czasie (równolegle), dzięki czemu wyniki mogą zostać dostarczone wcześniej, niż gdyby obliczenia zostały wykonane sekwencyjnie.

Natomiast współbieżność jest techniką strukturyzującą program, w której istnieje wiele wątków kontroli. Wątki kontroli wykonują się „w tym samym czasie”; to znaczy, użytkownik widzi, że ich efekty są przeplatane. To, czy faktycznie wykonują się w tym samym czasie, czy nie, jest szczegółem implementacji; współbieżny program może być wykonywany na jednym procesorze poprzez przeplatanie lub na wielu procesorach fizycznych.

Polecam przeczytać resztę w samouczku (s. 4), ale pozwól mi zacytować resztę tego rozdziału, ponieważ łączy on oba paradygmaty programowania z ilościowymi i jakościowymi cechami programów, takimi jak wydajność, modułowość i determinizm.

Podczas gdy programowanie równoległe dotyczy wyłącznie wydajności, programowanie współbieżne dotyczy struktury programu, który musi wchodzić w interakcje z wieloma niezależnymi agentami zewnętrznymi (na przykład użytkownikiem, serwerem bazy danych i niektórymi klientami zewnętrznymi). Współbieżność pozwala modułowym programom; wątek, który wchodzi w interakcję z użytkownikiem, różni się od wątku, który komunikuje się z bazą danych. W przypadku braku współbieżności, takie programy muszą być pisane z pętlami zdarzeń i wywołaniami zwrotnymi --- w rzeczywistości pętle zdarzeń i wywołania zwrotne są często używane, nawet gdy dostępna jest współbieżność, ponieważ w wielu językach współbieżność jest albo zbyt droga, albo zbyt trudna, aby posługiwać się.

Pojęcie „wątków kontroli” nie ma sensu w czysto funkcjonalnym programie, ponieważ nie ma żadnych efektów do zaobserwowania, a kolejność oceny jest nieistotna. Współbieżność jest więc techniką strukturyzującą efektywnego kodu; w Haskell oznacza to kod w monadzie IO.

Powiązane jest rozróżnienie między deterministycznymi i niedeterministycznymi modelami programowania. Deterministyczny model programowania to taki, w którym każdy program może dać tylko jeden wynik, podczas gdy niedeterministyczny model programowania dopuszcza programy, które mogą mieć różne wyniki, w zależności od pewnego aspektu wykonania. Współbieżne modele programowania są z konieczności niedeterministyczne, ponieważ muszą wchodzić w interakcje z agentami zewnętrznymi, które powodują zdarzenia w nieprzewidzianych momentach. Niedeterminizm ma jednak pewne istotne wady: programy stają się znacznie trudniejsze do przetestowania i uzasadnienia.

W przypadku programowania równoległego chcielibyśmy stosować deterministyczne modele programowania, jeśli to w ogóle możliwe. Ponieważ celem jest szybsze dotarcie do odpowiedzi, wolelibyśmy, aby nasz program nie był trudniejszy do debugowania w tym procesie. Deterministyczne programowanie równoległe jest najlepsze z obu światów: testowanie, debugowanie i wnioskowanie można wykonywać na programie sekwencyjnym, ale program działa szybciej po dodaniu procesorów. Rzeczywiście, większość samych procesorów komputerowych realizuje deterministyczną równoległość w postaci potoków i wielu jednostek wykonawczych.

Chociaż możliwe jest wykonywanie programowania równoległego przy użyciu współbieżności, jest to często zły wybór, ponieważ współbieżność rezygnuje z determinizmu. W Haskell równoległe modele programowania są deterministyczne. Należy jednak zauważyć, że deterministyczne modele programowania nie są wystarczające do wyrażenia wszystkich rodzajów równoległych algorytmów; istnieją algorytmy, które zależą od wewnętrznego niedeterminizmu, szczególnie problemy związane z wyszukiwaniem przestrzeni rozwiązania. W Haskell ta klasa algorytmów jest możliwa do wyrażenia tylko przy użyciu współbieżności.

nickie
źródło
20

Współbieżność i równoległość różnią się problemami, które rozwiązują i powodują, ale nie są niezależne.

Konkurencja

Wykonywanie dwóch zadań jednocześnie oznacza, że ​​poszczególne kroki obu zadań są wykonywane w sposób przeplatany. Pomijając paralelizm, można założyć, że w danym momencie wykonywana jest tylko jedna instrukcja, ale nie ma (a priori) gwarancji, które zadanie wykona następny krok.

Jest to przydatne w niektórych aspektach:

  • Przejrzystsze programowanie niezależnych zadań w jednym programie.
  • Pozwala radzić sobie z IO podczas przetwarzania (np. W GUI).
  • Pozwala na wykonywanie więcej niż jednego programu na raz (współbieżność na poziomie systemu operacyjnego).

Niektóre z głównych wyzwań to:

  • Zachowaj spójność danych.
  • Unikaj zakleszczeń i blokady na żywo .
  • Określ precyzyjną semantykę współbieżnych procesów.
  • Określ właściwości statyczne zapewniające poprawność.

Równoległość

Wykonywanie dwóch zadań równolegle oznacza, że ​​instrukcje są wykonywane jednocześnie . Jest to przydatne głównie w przypadku:

  • Popraw przepustowość systemu, uruchamiając programy równolegle (np. W systemach wielordzeniowych).
  • Popraw czas działania poszczególnych programów, wykorzystując wiele procesorów jednocześnie.
  • Wykorzystaj IO na wielu komputerach (np. Rozproszonych bazach danych).

Kluczowe wyzwania obejmują:

  • Problemy z partycjami, które pozwalają i opracowują algorytmy, które mogą wykorzystywać równoległość.
  • Zminimalizuj zależności i komunikację między jednostkami obliczeniowymi.
  • Wszystkie problemy związane z współbieżnością: przynajmniej z punktu widzenia pamięci programy równoległe wyglądają jak te współbieżne z powodu szeregowania dostępów do pamięci.
  • Poradzić sobie z nieoptymalnym wsparciem sprzętowym.

Zobacz także to pytanie dotyczące rozróżnienia przetwarzania równoległego i rozproszonego.

Raphael
źródło
4

Nieco idealna odpowiedź, być może ...

  • Współbieżność to właściwość pisania programu . Jeśli program jest napisany przy użyciu konstrukcji takich jak rozwidlenia / złączenia, blokady, transakcje, atomowe operacje porównywania i zamiany itd., To jest on współbieżny.

  • Równoległość to właściwość wykonywania programu . Jeśli program wykonuje się jednocześnie na więcej niż jednej jednostce obliczeniowej, wówczas jest wykonywany równolegle.

John Wickerson
źródło
1

Jest na to mnóstwo odpowiedzi, ale może to być mylące. Lubię myśleć o tym w ten sposób, a może to pomaga ?:

Programowanie współbieżne to kod, który nie dba o kolejność wykonywania. Java jest słabym językiem do równoczesnego programowania, ale istnieją biblioteki i frameworki, które mogą pomóc. JavaScript jest doskonałym językiem do równoczesnego programowania i często jest trudny, gdy chcesz napisać coś, co nie jest współbieżne (np. Jeśli chcesz wymusić kolejność wykonywania). Programowanie współbieżne doskonale nadaje się do programowania sterowanego zdarzeniami (gdzie kolejność wykonywania jest określana przez detektory zdarzeń, takie jak kod działający w przeglądarce, który działa po kliknięciu przycisku lub wpisaniu w polu).

Przykładem może być utworzenie stu żądań HTTP. W NodeJS najprostszym rozwiązaniem jest otwarcie wszystkich 100 żądań jednocześnie za pomocą metody wywołania zwrotnego, a gdy odpowiedzi wrócą, metoda jest wykonywana za każdym razem. To jest programowanie równoległe. W Ruby najprostszym (najczęstszym) rozwiązaniem jest otwarcie żądania i obsłużenie odpowiedzi, otwarcie następnego żądania i obsłużenie odpowiedzi itp. W przypadku wielu żądań NodeJS jest łatwiejszy do zrobienia w odpowiednim czasie, chociaż musisz być staraj się unikać uderzania serwera lub maksymalizacji połączeń wychodzących (łatwo to zrobić przez pomyłkę). Możesz napisać Ruby jednocześnie, ale nie jest tak, jak napisano większość kodu Rubiego, i to trochę boli.

Programowanie równoległeto kod, który można uruchamiać jednocześnie w wielu wątkach lub procesach. Pozwala to zoptymalizować wydajność, uruchamiając kod na wielu procesorach (często w tym na wielu komputerach, jak w przypadku czegoś takiego jak Akka). Ponieważ NodeJS nie jest wielowątkowy i nie ma równoległego wykonywania, nie musisz się martwić pisaniem kodu zabezpieczającego wątki (a większość kodu JavaScript, który widziałem, nie jest wątkowo bezpieczny). W Javie, mimo że język nie sprawia, że ​​programowanie równoległe jest normalnym wzorcem, programowanie równoległe jest bardzo wbudowane i często musisz martwić się o bezpieczeństwo wątków. Jeśli piszesz witrynę w języku Java, zazwyczaj będzie ona uruchamiana w kontenerze, który uruchamia każde żądanie w osobnym wątku w tej samej pamięci,


Niektóre z powyższych zależą od zakresu i granic, o których mówisz. Pracuję na stronach internetowych. Większość kodu Java, który widzę, nie jest programowaniem współbieżnym. Oczywiście, jeśli odpowiednio pomniejszysz, kolejność, w której przychodzą żądania klienta, nie jest ważna, ale jeśli powiększysz dalej, kolejność wykonania rzeczy jest podyktowana przez kod. Ale kod jest napisany, aby żądania mogły być wykonywane równolegle z wieloma współdzielonymi obiektami, które muszą być bezpieczne dla wątków.

Tymczasem większość kodu JavaScript, który widzę, jest współbieżna: jest napisana w taki sposób, że kolejność wykonywania jest nieistotna na wielu poziomach. Ale nie jest napisane, aby obsługiwać równoległe wykonywanie w pamięci współdzielonej. Oczywiście możesz wykonywać ten sam kod równolegle w wielu procesach, ale obiekty nie są współużytkowane, więc nie jest to programowanie równoległe w żadnym sensownym sensie.

Dla dodatkowej lektury bardzo podobają mi się ilustracje w górnej odpowiedzi na to pytanie tutaj: https://www.quora.com/What-are-the-differences-between-parallel-concurrent-and-asynchronous-programming

Jun-Dai Bates-Kobashigawa
źródło