Aby założyć poprawę szybkości ze względu na jakąkolwiek formę przetwarzania wielu komputerów, należy założyć, że wiele zadań opartych na procesorach jest wykonywanych jednocześnie na wielu zasobach obliczeniowych (zazwyczaj rdzeniach procesora) lub że nie wszystkie zadania zależą od równoczesnego użycia ten sam zasób - to znaczy, że niektóre zadania mogą zależeć od jednego podkomponentu systemu (powiedzmy pamięć dyskowa), podczas gdy niektóre zadania zależą od innego (odbieranie komunikacji z urządzenia peryferyjnego), a jeszcze inne mogą wymagać użycia rdzeni procesora.
Pierwszy scenariusz jest często nazywany programowaniem „równoległym”. Drugi scenariusz jest często określany jako programowanie „współbieżne” lub „asynchroniczne”, chociaż termin „współbieżny” jest czasami używany również w odniesieniu do przypadku, gdy po prostu zezwala się systemowi operacyjnemu na przeplatanie wykonywania wielu zadań, niezależnie od tego, czy takie wykonanie musi zająć umieszczać szeregowo lub jeśli można użyć wielu zasobów, aby uzyskać wykonywanie równoległe. W tym drugim przypadku określenie „współbieżne” odnosi się ogólnie do sposobu, w jaki wykonanie jest zapisywane w programie, a nie z perspektywy faktycznej jednoczesności wykonywania zadań.
Bardzo łatwo o tym wszystkim mówić z milczącymi założeniami. Na przykład niektórzy szybko zgłaszają oświadczenie, takie jak „Asynchroniczne operacje we / wy będą szybsze niż wielowątkowe we / wy”. To twierdzenie jest wątpliwe z kilku powodów. Po pierwsze, może się zdarzyć, że pewna podana asynchroniczna struktura we / wy jest zaimplementowana dokładnie z wielowątkowością, w którym to przypadku są one tym samym i nie ma sensu mówić, że jedna koncepcja „jest szybsza” niż druga .
Po drugie, nawet w przypadku, gdy istnieje jednowątkowa implementacja struktury asynchronicznej (np. Jednowątkowa pętla zdarzeń), nadal należy przyjąć założenie dotyczące tego, co robi ta pętla. Na przykład jedną głupią rzeczą, jaką można zrobić z jednowątkową pętlą zdarzeń, jest żądanie asynchronicznego wykonania dwóch różnych zadań związanych wyłącznie z procesorem. Jeśli zrobiłeś to na maszynie z wyidealizowanym rdzeniem pojedynczego procesora (ignorując współczesne optymalizacje sprzętowe), wykonanie tego zadania „asynchronicznie” nie byłoby tak naprawdę inne niż wykonanie go z dwoma niezależnie zarządzanymi wątkami lub tylko z jednym samotnym procesem - - różnica może sprowadzać się do przełączania kontekstu wątków lub optymalizacji harmonogramu systemu operacyjnego, ale jeśli oba zadania są kierowane do procesora, w obu przypadkach byłoby podobnie.
Warto wyobrazić sobie wiele nietypowych lub głupich przypadków narożnych, na które możesz się natknąć.
„Asynchroniczny” nie musi być współbieżny, na przykład tak jak powyżej: „asynchronicznie” wykonujesz dwa zadania związane z procesorem na maszynie z dokładnie jednym rdzeniem procesora.
Wykonywanie wielowątkowe nie musi być współbieżne: tworzysz dwa wątki na maszynie z jednym rdzeniem procesora lub prosisz dwa wątki o pozyskanie innego rodzaju rzadkiego zasobu (wyobraź sobie, na przykład, sieciową bazę danych, która może ustanowić tylko jeden połączenie na raz). Wykonywanie wątków może być przeplatane, jednak harmonogram systemu operacyjnego uzna to za stosowne, ale ich całkowity czas wykonywania nie może zostać zmniejszony (i zostanie zwiększony z przełączania kontekstu wątku) na jednym rdzeniu (lub bardziej ogólnie, jeśli spawnujesz więcej wątków niż jest) rdzeni, aby je uruchomić lub mieć więcej wątków proszących o zasób, niż to, co zasób może utrzymać). To samo dotyczy również przetwarzania wielokrotnego.
Zatem ani asynchroniczne operacje we / wy, ani wielowątkowość nie muszą oferować żadnego wzrostu wydajności pod względem czasu wykonywania. Mogą nawet spowolnić działanie.
Jeśli jednak zdefiniujesz konkretny przypadek użycia, taki jak określony program, który zarówno wykonuje wywołanie sieciowe w celu pobrania danych z zasobu podłączonego do sieci, takiego jak zdalna baza danych, a także wykonuje pewne lokalne obliczenia związane z procesorem, możesz zacząć rozważać różnice w wydajności między tymi dwiema metodami przy określonym założeniu dotyczącym sprzętu.
Pytania, które należy zadać: Ile kroków obliczeniowych muszę wykonać i ile jest niezależnych systemów zasobów, aby je wykonać? Czy istnieją podzbiory kroków obliczeniowych, które wymagają użycia niezależnych podskładników systemu i mogą przynosić korzyści z robienia tego jednocześnie? Ile mam rdzeni procesorów i jakie są narzuty związane z używaniem wielu procesorów lub wątków do wykonywania zadań na oddzielnych rdzeniach?
Jeśli Twoje zadania w dużej mierze opierają się na niezależnych podsystemach, rozwiązanie asynchroniczne może być dobre. Jeśli liczba wątków potrzebnych do jego obsługi byłaby duża, tak że przełączanie kontekstu stało się nietrywialne dla systemu operacyjnego, wówczas rozwiązanie asynchroniczne jednowątkowe mogłoby być lepsze.
Ilekroć zadania są powiązane przez ten sam zasób (np. Wiele potrzeb, aby jednocześnie uzyskać dostęp do tej samej sieci lub zasobu lokalnego), wówczas wielowątkowość prawdopodobnie wprowadzi niezadowalający narzut, a podczas gdy asynchronia jednowątkowa może wprowadzić mniejszy narzut, w takim zasobie ograniczona sytuacja to również nie może spowodować przyspieszenia. W takim przypadku jedyną opcją (jeśli chcesz przyspieszyć) jest udostępnienie wielu kopii tego zasobu (np. Wielu rdzeni procesora, jeśli rzadkim zasobem jest procesor; lepsza baza danych, która obsługuje więcej równoczesnych połączeń, jeśli rzadki zasób to baza danych z ograniczeniem połączeń itp.).
Można to ująć w inny sposób: zezwolenie systemowi operacyjnemu na przeplatanie wykorzystania jednego zasobu do dwóch zadań nie może być szybsze niż zwykłe pozwolenie jednemu zadaniu na wykorzystanie zasobu, podczas gdy drugie czeka, a następnie pozwolenie drugiemu zadaniu na kolejne zakończenie. Co więcej, koszt planistycznego przeplatania oznacza, że w każdej rzeczywistej sytuacji faktycznie powoduje spowolnienie. Nie ma znaczenia, czy użycie z przeplotem dotyczy procesora, zasobu sieciowego, zasobu pamięci, urządzenia peryferyjnego czy jakiegokolwiek innego zasobu systemowego.