Są to dwa wyrażenia, które opisują to samo z (bardzo nieznacznie) różnych punktów widzenia. Programowanie równoległe opisuje sytuację z punktu widzenia sprzętu - przynajmniej dwa procesory (być może w ramach jednego pakietu fizycznego) pracują równolegle nad problemem. Programowanie współbieżne opisuje więcej rzeczy z punktu widzenia oprogramowania - dwie lub więcej akcji może się wydarzyć dokładnie w tym samym czasie (jednocześnie).
Problem polega na tym, że ludzie próbują użyć tych dwóch wyrażeń, aby wyraźnie rozróżnić, kiedy tak naprawdę nie istnieje. Rzeczywistość jest taka, że linia podziału, którą próbują narysować, jest rozmyta i niewyraźna od dziesięcioleci, a z czasem staje się coraz bardziej niewyraźna.
To, co próbują omówić, to fakt, że dawno temu większość komputerów miała tylko jeden procesor. Kiedy wykonałeś wiele procesów (lub wątków) na tym samym CPU, procesor tak naprawdę wykonywał tylko jedną instrukcję z jednego z tych wątków na raz. Pojawienie się współbieżności było złudzeniem - procesor przełączał się pomiędzy wykonywaniem instrukcji z różnych wątków wystarczająco szybko, aby dla ludzkiej percepcji (do której wszystko mniej niż 100 ms lub mniej wygląda natychmiast) wyglądało to tak, jakby robiło wiele rzeczy naraz.
Oczywistym przeciwieństwem jest komputer z wieloma procesorami lub procesor z wieloma rdzeniami, więc maszyna wykonuje instrukcje z wielu wątków i / lub procesów dokładnie w tym samym czasie; kod wykonujący jeden nie może / nie ma żadnego wpływu na wykonanie kodu w drugim.
Teraz problem: takie czyste rozróżnienie prawie nigdy nie istniało. Projektanci komputerów są właściwie dość inteligentni, więc dawno temu zauważyli, że (na przykład), kiedy trzeba było odczytać niektóre dane z urządzenia we / wy, takiego jak dysk, zajęło to dużo czasu czasu (pod względem cykli procesora) koniec. Zamiast pozostawiać procesor bezczynny w tym czasie, wymyślili różne sposoby pozwalania jednemu procesowi / wątkowi na wysłanie żądania we / wy i pozwolenie na wykonanie kodu z innego procesu / wątku na procesorze po zakończeniu żądania we / wy.
Tak więc, na długo przed tym, jak wielordzeniowe procesory stały się normą, mieliśmy równoległe operacje z wielu wątków.
To tylko wierzchołek góry lodowej. Kilkadziesiąt lat temu komputery zaczęły również zapewniać kolejny poziom równoległości. Ponownie, będąc dość inteligentnymi ludźmi, projektanci komputerów zauważyli, że w wielu przypadkach mieli instrukcje, które nie wpływają na siebie nawzajem, więc można było wykonać więcej niż jedną instrukcję z tego samego strumienia w tym samym czasie. Jednym z pierwszych przykładów, który stał się dość dobrze znany, był Control Data 6600. Był to (z dość szerokim marginesem) najszybszy komputer na świecie, kiedy został wprowadzony w 1964 roku - i wiele z tej samej podstawowej architektury pozostaje w użyciu do dziś. Śledził zasoby wykorzystywane przez każdą instrukcję i miał zestaw jednostek wykonawczych, które wykonywały instrukcje, gdy tylko zasoby, od których były zależne, stały się dostępne, bardzo podobne do konstrukcji najnowszych procesorów Intel / AMD.
Ale (jak mawiano w reklamach) czekaj - to nie wszystko. Jest jeszcze jeden element projektu, który jeszcze bardziej wprowadza zamieszanie. Nadano mu kilka różnych nazw (np. „Hyperthreading”, „SMT”, „CMP”), ale wszystkie odnoszą się do tego samego podstawowego pomysłu: procesora, który może wykonywać wiele wątków jednocześnie, używając kombinacji niektórych zasobów, które są niezależne dla każdego wątku, a niektóre zasoby są współużytkowane między wątkami. W typowym przypadku jest to połączone z równoległością na poziomie instrukcji opisaną powyżej. Aby to zrobić, mamy dwa (lub więcej) zestawy rejestrów architektonicznych. Następnie mamy zestaw jednostek wykonawczych, które mogą wykonywać instrukcje, gdy tylko dostępne zasoby będą dostępne.
Następnie oczywiście dochodzimy do nowoczesnych systemów z wieloma rdzeniami. Tutaj rzeczy są oczywiste, prawda? Mamy N (gdzieś pomiędzy 2 a 256) oddzielnych rdzeni, które mogą wszystkie wykonywać instrukcje w tym samym czasie, więc mamy wyraźny przypadek prawdziwej równoległości - wykonywanie instrukcji w jednym procesie / wątku nie jest t wpływać na wykonywanie instrukcji w innym.
Cóż, w pewnym sensie. Nawet tutaj mamy pewne niezależne zasoby (rejestry, jednostki wykonawcze, co najmniej jeden poziom pamięci podręcznej) i niektóre zasoby współdzielone (zazwyczaj co najmniej najniższy poziom pamięci podręcznej, a na pewno kontrolery pamięci i przepustowość pamięci).
Podsumowując: proste scenariusze, które ludzie lubią zestawiać między zasobami współdzielonymi a zasobami niezależnymi, praktycznie nigdy się nie zdarzają. Po udostępnieniu wszystkich zasobów powstaje coś w rodzaju MS-DOS, w którym możemy uruchomić tylko jeden program na raz i musimy zatrzymać jeden, zanim będziemy mogli uruchomić drugi. Dysponując całkowicie niezależnymi zasobami, mamy N komputerów z systemem MS-DOS (nawet bez sieci, aby je połączyć), bez żadnej możliwości współdzielenia czegokolwiek między nimi (ponieważ jeśli możemy nawet udostępnić plik, to jest to udostępniony zasób, naruszenie podstawowej przesłanki, że nic nie jest udostępniane).
Każdy interesujący przypadek obejmuje pewną kombinację niezależnych zasobów i wspólnych zasobów. Każdy rozsądnie nowoczesny komputer (i wiele, które wcale nie są nowoczesne) ma przynajmniej pewną zdolność do wykonywania co najmniej kilku niezależnych operacji jednocześnie, i prawie wszystko, co jest bardziej wyrafinowane niż MS-DOS, skorzystało z tego przynajmniej pewien stopień.
Ładny, czysty podział między „równoczesnym” a „równoległym”, który ludzie lubią rysować, po prostu nie istnieje i prawie nigdy go nie ma. To, co ludzie lubią klasyfikować jako „współbieżne”, zwykle nadal wiąże się z co najmniej jednym, a często więcej, rodzajem równoległego wykonywania. To, co lubią klasyfikować jako „równoległe”, często polega na współdzieleniu zasobów i (na przykład) jednym procesie blokującym wykonanie drugiego podczas korzystania z zasobu, który jest dzielony między nimi.
Ludzie próbujący wyraźnie rozróżnić „równoległy” i „równoległy” żyją w fantazji o komputerach, które nigdy nie istniały.