CodeGym /Kursy /Python SELF PL /Wielowątkowość

Wielowątkowość

Python SELF PL
Poziom 25 , Lekcja 0
Dostępny

1.1 Historia powstania

Ludzkość często wpada na pomysł stworzenia nowego, niesamowitego projektu, który przyćmi wszystkie poprzednie. Piramida Cheopsa w Gizie — największa, Burdż Chalifa w Dubaju — najwyższa, a Wielki Mur Chiński — najdłuższy.

Organizacja pracy nad takimi projektami to jednak trudne zadanie. Jeśli chcielibyśmy zbudować nową piramidę dwa razy wyższą, to potrzeba na to osiem razy więcej kamienia. Znaczy to, że musimy albo zwiększyć wydajność kamieniołomów, albo otworzyć więcej kopalni.

Również trzeba będzie znaleźć ośmiokrotnie więcej inżynierów, możliwe, że otworzyć szkoły inżynierskie, standaryzować plany budowy, geometrię, pismo. Słowem, niezła łamigłówka...

Tysiące lat po budowie piramid nic się nie zmieniło — nadal ludzie myślą, jak zrobić więcej w krótszym czasie. I kiedy wynaleziono komputery, nad tym problemem zaczęły pracować największe umysły ludzkości.

Jak wykonać program dziesięć razy szybciej? Wydawać by się mogło, że to dziwne pytanie — jeśli procesor już pracuje z maksymalną prędkością, to pewnie się nie da. Jednak nie bez powodu wspomniałem o najlepszych umysłach ludzkości. Oni przeanalizowali działanie wszystkich programów i doszli do wniosku, że są trzy główne kierunki rozwoju.

Eliminacja przestojów

Okazuje się, że przez większość czasu program przerywa pracę. Stale czegoś oczekuje: dane muszą zostać skopiowane z jednego miejsca pamięci do innego, załadowane z dysku twardego do pamięci, trzeba czekać na odpowiedź serwera na żądanie, na dane wejściowe od użytkownika itp.

Wszystkie te zadania są wykonywane nie przez centralny procesor, tylko przez kontrolery pamięci, dysku i tak dalej. I centralny procesor w tym czasie mógłby być obciążony czymś pożytecznym. Tak pojawił się pomysł uruchamiania w jednym procesorze nie jednego, lecz kilku wątków wykonywania poleceń (thread).

I o ile, na przykład, jeden wątek czeka na dane wejściowe od użytkownika, drugi pobiera coś z sieci, trzeci przetwarza dane, czwarty renderuje obrazy na ekranie. Potem ta koncepcja ewoluuje do zadań asynchronicznych i korutyn, ale o tym później.

Więcej programów

Jeśli programy przerywają pracę przez 80% czasu, to oczywiście nie jest dobrze. Z drugiej strony, nie można przecież przepisać wszystkich programów pod nasze nowe podejścia. Może problem można rozwiązać inaczej — wystarczy uruchamiać na komputerze kilka programów jednocześnie.

W tym przypadku system operacyjny nadzoruje pracę programów i jeśli program przerywa pracę, to przekazuje jego czas wykonania innemu programowi. Takie przełączanie odbywa się dziesiątki razy na sekundę, a użytkownik nie zauważa tych zmian — w jego oczach programy działają jednocześnie.

Więcej procesorów

Równoczesne wykonanie programów jest świetne, ale co jeśli programów jest wiele, a przerwy są mało? Brak przerw — brak efektywnego wykorzystania. Na przykład, mamy dziesięć programów obliczających coś, lub zasobożerną grę i jeszcze coś razem z nią.

Rozwiązaniem tego problemu stało się dodanie do procesora kilku procesorów. Aby uniknąć zamieszania, zaczęto je nazywać rdzeniami. Teraz mamy procesory, które mają wiele rdzeni (sub-procesorów), na których równolegle działają dziesiątki programów.

To jest interesujące! Liczba rdzeni w procesorach

Na dzień dzisiejszy procesory serwerowe mogą mieć od 64 do 256 rdzeni, a w niektórych wyspecjalizowanych przypadkach nawet więcej. Na przykład procesory AMD EPYC czwartej generacji oferują do 96 rdzeni, a IBM POWER10 może mieć do 240 rdzeni na chip. Procesory użytkowe także znacznie ewoluowały: wysokowydajne procesory desktopowe, takie jak AMD Threadripper, mogą mieć do 64 rdzeni, podczas gdy bardziej powszechne modele zwykle mają od 6 do 16 rdzeni.

Co dalej? Jest jeszcze wiele do zrobienia! Po pierwsze, na jednej płycie głównej serwera można zainstalować kilka procesorów, na przykład dwa lub nawet cztery. Po drugie, serwery można łączyć w stojaki serwerowe po 10-20 sztuk. A stojaki serwerowe — w centra danych, gdzie takich stojaków są tysiące.

Systemy rozproszone i architektury mikroserwisowe stały się powszechną praktyką w nowoczesnym rozwoju oprogramowania. Wielkie firmy, takie jak Google, Amazon, Netflix, a także mniejsze przedsiębiorstwa, wykorzystują systemy rozproszone do przetwarzania dużych ilości danych, zapewnienia wysokiej dostępności i skalowalności swoich usług. Systemy te pozwalają efektywnie wykorzystywać zasoby wielu serwerów, które działają razem jako jedna całość, co znacznie podnosi wydajność i odporność na awarie aplikacji.

1.2 Korzyści

Wielowątkowość, czyli jednoczesne wykonywanie zadań wewnątrz programu, oferuje kilka kluczowych korzyści, które mogą znacznie poprawić wydajność i efektywność oprogramowania. Przyjrzyjmy się głównym zaletom wielowątkowości.

1. Zwiększenie wydajności i szybkości wykonywania

Równoczesne wykonywanie zadań: Wielowątkowość pozwala wykonywać wiele zadań jednocześnie, co jest szczególnie przydatne dla programów wymagających wykonania licznych niezależnych operacji. To pozwala przyspieszyć wykonanie programu, ponieważ zadania wykonywane są równolegle, wykorzystując wszystkie dostępne zasoby procesora.

Wykorzystanie procesorów wielordzeniowych: Nowoczesne procesory mają wiele rdzeni, a wielowątkowość pozwala w pełni wykorzystać ich moc, rozdzielając wątki na różne rdzenie do wykonywania zadań równolegle.

2. Poprawa responsywności i interakcji z użytkownikiem

Zadania w tle: Wielowątkowość pozwala wykonywać długotrwałe lub zasobożerne operacje w tle, jednocześnie zachowując główny wątek odpowiadający za interfejs użytkownika responsywnym. To poprawia doświadczenie użytkownika, ponieważ interfejs nie blokuje się podczas wykonywania ciężkich zadań.

Operacje asynchroniczne: Interakcja z użytkownikiem i przetwarzanie zdarzeń mogą odbywać się równolegle z wykonywaniem głównych zadań, co sprawia, że aplikacje są bardziej responsywne i efektywne.

3. Efektywne wykorzystanie zasobów systemu

Optymalizacja zasobów: Wielowątkowość pozwala bardziej efektywnie wykorzystać zasoby systemu, takie jak czas procesora i pamięć. Jest to szczególnie ważne dla serwerów i wysokowydajnych systemów obliczeniowych, gdzie wielowątkowość pozwala przetwarzać wiele żądań i zadań jednocześnie.

Zarządzanie wejściem-wyjściem: Aplikacje wielowątkowe mogą zarządzać zadaniami wejścia-wyjścia (np. operacjami sieciowymi, odczytem i zapisem plików) bardziej efektywnie, ponieważ wątki mogą wykonywać inne zadania, podczas gdy jedno z nich czeka na zakończenie operacji wejścia-wyjścia.

4. Wsparcie dla wielozadaniowości

Wielozadaniowość: Wielowątkowość pozwala wykonywać wiele zadań jednocześnie w ramach jednego procesu, co ułatwia tworzenie aplikacji, które wymagają wielozadaniowości, takich jak serwery internetowe, bazy danych i aplikacje czasu rzeczywistego.

Równoległe przetwarzanie danych: W zadaniach związanych z przetwarzaniem dużych ilości danych, wielowątkowość pozwala dzielić dane na części i przetwarzać je równolegle, co znacznie przyspiesza wykonanie zadania.

Przykłady zastosowania wielowątkowości

Serwery internetowe: Wielowątkowość pozwala serwerom internetowym obsługiwać wiele żądań klientów jednocześnie, zwiększając wydajność i skalowalność serwerów.

Graficzne interfejsy użytkownika (GUI): W aplikacjach z interfejsem graficznym wielowątkowość pozwala wykonywać długotrwałe obliczenia w tle, utrzymując interfejs responsywnym.

Obliczenia naukowe: Wielowątkowość jest używana do równoległego przetwarzania danych w obliczeniach naukowych, co pozwala znacznie przyspieszyć wykonywanie złożonych zadań obliczeniowych.

Gry i symulacje: W grach wielowątkowość pozwala jednocześnie przetwarzać fizykę, grafikę, dźwięki i działania użytkownika, poprawiając wydajność i realizm.

1.3 Prawidłowa nazwa

W nazwie „wielowątkowość” są pewne zastrzeżenia. Składa się ona z dwóch słów: „wiele” i „wątek”, jakby sugerując, że wewnątrz programu znajduje się wiele „threadów wykonywania poleceń”, które coś robią.

Piękna analogia, ale w literaturze angielskiej (oryginalnej) do oznaczania kilku równolegle wykonywanych działań używa się terminu „thread” (thread). I odpowiednio, wielowątkowość tam to multi-threading.

Można by to uznać za drobne nieporozumienie — kogo obchodzi, jak różne terminy są tłumaczone na inne języki, gdyby w programowaniu nie zaczęto aktywnie używać czegoś takiego jak stream, które poza słowem „strumień” nie da się przetłumaczyć.

Dlatego teraz w terminologii rosyjskojęzycznej istnieje pewne zamieszanie, które rozwiązuje się na dwa sposoby:

  • Thread (wątek) tłumaczy się jako „thread wykonywania [poleceń]”.
  • Stream (strumień) tłumaczy się jako „strumień danych”.

Z drugiej strony, wielu programistów po prostu zaczęło używać angielskich terminów bez tłumaczenia:

  • Thread (wątek) wymawiają jako „thread”, a multi-threading jako „multi-threading”.
  • Stream (strumień) wymawiają jako „stream”.

Thread często nazywa się wątkiem, ale termin „wielowątkowość” tak i nie przyjął się. Dlatego często w rozmowach używa się „wątek” i „wielowątkowość” równocześnie.

Użycie dużej liczby zapożyczonych terminów sprawia, że język staje się bogatszy, pozwala na wypełnienie słów nowym znaczeniem i upraszcza komunikację z kolegami z innych krajów. Całkowicie popieram takie podejście.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION