Co to jest coroutine? Jak są one powiązane z współbieżnością?
Co to jest coroutine? Jak są one powiązane z współbieżnością?
Odpowiedzi:
Korpusy i współbieżność są w dużej mierze ortogonalne. Korpusy są ogólną strukturą kontrolną, w której kontrola przepływu jest wspólnie przekazywana między dwiema różnymi procedurami bez powrotu.
Polecenie „fed” w Pythonie jest dobrym przykładem. Tworzy kortynę. Po napotkaniu „wydajności” zapisywany jest bieżący stan funkcji, a kontrola powraca do funkcji wywołującej. Funkcja wywołująca może następnie przenieść wykonanie z powrotem do funkcji ustępującej, a jej stan zostanie przywrócony do punktu, w którym napotkano „wydajność” i wykonywanie będzie kontynuowane.
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.
<- To jest współbieżność. Słowo, którego szukasz, to równoległość.
orthogonal = Not similar to each other
?
orthogonal
oznacza to „niezależne od siebie”.
Z programowania w Lua , Coroutines
sekcja „ ”:
Korpus jest podobny do wątku (w sensie wielowątkowości): jest to linia wykonania, z własnym stosem, własnymi zmiennymi lokalnymi i własnym wskaźnikiem instrukcji; ale ma wspólne zmienne globalne i głównie wszystko inne z innymi firmami. Główna różnica między wątkami a coroutines polega na tym, że koncepcyjnie (lub dosłownie w maszynie wieloprocesorowej) program z wątkami uruchamia kilka wątków równolegle. Z drugiej strony, coroutines współpracują ze sobą: w dowolnym momencie program z coroutines uruchamia tylko jedną ze swoich coroutines, a ta uruchomiona coroutine zawiesza wykonywanie tylko wtedy, gdy wyraźnie żąda zawieszenia.
Chodzi o to, że coroutine są „współpracujące”. Nawet w systemie wielordzeniowym w danym momencie działa tylko jedna koruta (ale wiele wątków może działać równolegle). Między korporacjami nie ma prawa zapobiegawczego, działająca coroutine musi jawnie zrezygnować z wykonania.
Aby zobaczyć „ concurrency
”, możesz odnieść slajd Roba Pike'a :
Współbieżność to kompozycja niezależnie wykonujących obliczeń.
Tak więc podczas wykonywania coroutine A przekazuje kontrolę do coroutine B. Następnie po pewnym czasie coroutine B przekazuje kontrolę z powrotem do coroutine A. Ponieważ istnieje zależność między coroutine i muszą one działać w tandemie, więc dwie coroutine nie są współbieżne .
Uważam, że większość odpowiedzi jest zbyt techniczna, mimo że jest to pytanie techniczne. Trudno mi było zrozumieć proces korupcji. W pewnym sensie to rozumiem, ale potem nie rozumiem tego w tym samym czasie.
Uważam, że ta odpowiedź tutaj jest bardzo pomocna:
https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9
Cytat z Idan Arye:
Aby rozwinąć twoją historię, chciałbym napisać coś takiego:
Zaczynasz oglądać kreskówkę, ale to jest wprowadzenie. Zamiast oglądać wstęp, przełączasz się do gry i wchodzisz do lobby online - ale potrzebuje 3 graczy i tylko ty i twoja siostra są w nim. Zamiast czekać na dołączenie innego gracza, przełącz się na pracę domową i odpowiedz na pierwsze pytanie. Drugie pytanie zawiera link do filmu na YouTube, który musisz obejrzeć. Otwierasz go - i zaczyna się ładować. Zamiast czekać na załadowanie, przełączasz się z powrotem na kreskówkę. Wstęp jest zakończony, więc możesz oglądać. Teraz są reklamy - ale tymczasem dołączył trzeci gracz, więc przełączasz się na grę I tak dalej ...
Chodzi o to, że nie tylko przełączasz zadania naprawdę szybko, aby wyglądało to tak, jakbyś robił wszystko od razu. Wykorzystujesz czas, który czekasz, aż coś się wydarzy (IO), aby wykonać inne czynności wymagające Twojej bezpośredniej uwagi.
Zdecydowanie sprawdź link, nie mogę wszystkiego zacytować.
Coroutine jest podobny do podprogramu / wątków. Różnica polega na tym, że gdy wywołujący wywoła podprogram / wątki, nigdy nie powróci do funkcji wywołującej. Ale coroutine może powrócić do programu wywołującego po wykonaniu kilku fragmentów kodu, umożliwiając programowi wywołującemu wykonanie własnego kodu i powrót do punktu coroutine, w którym przerwał wykonywanie i kontynuował stamtąd. to znaczy. Korpus ma więcej niż jeden punkt wejścia i wyjścia
Zasadniczo istnieją dwa rodzaje Coroutines:
Kotlin implementuje coroutines bez stosu - oznacza to, że coroutines nie mają własnego stosu, więc nie mapują się na natywny wątek.
Oto funkcje uruchamiania coroutine:
launch{}
async{}
Możesz dowiedzieć się więcej tutaj:
https://www.kotlindevelopment.com/deep-dive-coroutines/
https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9
Z Python Coroutine :
Wykonywanie coroutines w Pythonie można zawiesić i wznowić w wielu punktach (patrz coroutine). Wewnątrz funkcji coroutine czekają, a identyfikatory asynchroniczne stają się zastrzeżonymi słowami kluczowymi; czekaj na wyrażenia, asynchroniczne i asynchroniczne z mogą być używane tylko w obiektach funkcji coroutine.
Koruta jest funkcją, która może zawiesić wykonanie, aby zostać wznowiona później . Korpusy są bezładne: zawieszają wykonywanie, wracając do programu wywołującego. Pozwala to na sekwencyjny kod, który wykonuje się asynchronicznie (np. Do obsługi nieblokujących We / Wy bez wyraźnych wywołań zwrotnych), a także obsługuje algorytmy na leniwie obliczonych nieskończonych sekwencjach i innych zastosowaniach.
Porównaj z odpowiedzią innych:
Moim zdaniem wznowiona później część jest zasadniczą różnicą, podobnie jak @ Twinkle's.
Chociaż wiele pól dokumentu jest wciąż w toku, ta część jest podobna do większości odpowiedzi, z wyjątkiem @Nan Xiao
Z drugiej strony, coroutines współpracują ze sobą: w dowolnym momencie program z coroutines uruchamia tylko jedną ze swoich coroutines, a ta uruchomiona coroutine zawiesza wykonywanie tylko wtedy, gdy wyraźnie żąda zawieszenia.
Ponieważ cytat pochodzi z Programu w Lua, być może jest on związany z językiem (obecnie nie zna Lua), nie wszystkie dokumenty wspominają tylko o jednej części.
Relacja z równoczesnym:
w Coroutines znajduje się część „ Egzekucyjna” (C ++ 20) .
Oprócz szczegółów istnieje kilka stanów.
When a coroutine begins execution
When a coroutine reaches a suspension point
When a coroutine reaches the co_return statement
If the coroutine ends with an uncaught exception
When the coroutine state is destroyed either because it terminated via co_return or uncaught exception, or because it was destroyed via its handle
jako komentarz od @Adam Arold pod odpowiedzią @ user217714. To współbieżność.
Ale różni się od wielowątkowości.
z std :: thread
Wątki umożliwiają jednoczesne wykonywanie wielu funkcji. Wątki rozpoczynają wykonywanie natychmiast po zbudowaniu powiązanego obiektu wątku (w oczekiwaniu na opóźnienia w planowaniu systemu operacyjnego), zaczynając od funkcji najwyższego poziomu podanej jako argument konstruktora. Zwracana wartość funkcji najwyższego poziomu jest ignorowana, a jeśli zakończy się przez zgłoszenie wyjątku, wywoływane jest std :: terminate. Funkcja najwyższego poziomu może przekazać swoją wartość zwracaną lub wyjątek dzwoniącemu przez std :: promise lub przez modyfikację zmiennych wspólnych (które mogą wymagać synchronizacji, patrz std :: mutex i std :: atomic)
Ponieważ jest to współbieżność, działa jak wielowątkowość, zwłaszcza gdy nie da się uniknąć oczekiwania (z perspektywy systemu operacyjnego), dlatego też jest myląca.
Korpus jest szczególnym rodzajem podprogramu. Zamiast relacji master-slave między dzwoniącym a wywoływanym podprogramem, który istnieje w przypadku konwencjonalnych podprogramów, dzwoniący i nazywane coroutines są bardziej sprawiedliwi.
Korpus jest podprogramem, który ma wiele pozycji i sam je kontroluje - obsługiwany bezpośrednio w Lua
Nazywany również kontrolą symetryczną: osoba wywołująca i nazywane coroutines są na równych zasadach
Wezwanie coroutine nosi nazwę CV
Pierwsze wznowienie coroutine jest na początku, ale kolejne wywołania pojawiają się w punkcie tuż po ostatniej wykonanej instrukcji w coroutine
Korpusy wielokrotnie się wznawiają, być może na zawsze
Korpusy zapewniają quasi-równoczesne wykonywanie jednostek programu (coroutines); ich wykonanie jest przeplatane, ale nie nakłada się
Wyjaśnienie tego linku jest dość proste. Żadna z tych odpowiedzi nie próbuje wyjaśnić zbieżności z równoległością, z wyjątkiem ostatniego punktu w tej odpowiedzi .
cytowany z „programowania Erlanga” autorstwa legendarnego Joe Armstronga:
współbieżny program może działać potencjalnie szybciej na komputerze równoległym.
program współbieżny to program napisany w równoległym języku programowania. Piszemy programy współbieżne ze względu na wydajność, skalowalność lub odporność na awarie.
współbieżny język programowania to język, który ma wyraźne konstrukcje językowe do pisania współbieżnych programów. Te konstrukcje są integralną częścią języka programowania i zachowują się w ten sam sposób we wszystkich systemach operacyjnych.
komputer równoległy to komputer, który ma kilka jednostek przetwarzających (procesorów lub rdzeni), które mogą działać w tym samym czasie.
Zatem współbieżność to nie to samo co równoległość. Nadal możesz pisać współbieżne programy na komputerze z jednym rdzeniem. Harmonogram podziału czasu sprawi, że poczujesz, że twój program działa jednocześnie.
Współbieżny program może działać równolegle na komputerze równoległym, ale nie jest to gwarantowane . System operacyjny może dać ci tylko jeden rdzeń do uruchomienia twojego programu.
Dlatego współbieżność to model oprogramowania współbieżnego programu, który nie oznacza, że Twój program może działać równolegle fizycznie.
Słowo „coroutine” składa się z dwóch słów: „co” (spółdzielnia) i „procedury” (funkcje).
za. czy osiąga współbieżność lub równoległość?
Mówiąc prościej, omówmy to na jednym rdzeniu .
Współbieżność osiągana jest dzięki udziałom czasowym z systemu operacyjnego. Wątek wykonuje swój kod w przypisanych ramach czasowych na rdzeniu procesora. Może być przejęty przez system operacyjny. Może także sprawować kontrolę nad systemem operacyjnym.
Z drugiej strony, coroutine daje kontrolę nad inną coroutine w wątku, a nie OS. Tak więc wszystkie coroutines w wątku nadal wykorzystują ramy czasowe tego wątku bez poddawania rdzenia procesora innym wątkom zarządzanym przez system operacyjny.
Dlatego możesz pomyśleć, że coroutine osiąga udziały czasu przez użytkownika, a nie przez system operacyjny (lub quasi-równoległość). Coroutines działają na tym samym rdzeniu, który jest przypisany do wątku, który uruchamia te coroutines.
Czy Coroutine osiąga równoległość? Jeśli jest to kod związany z procesorem, nie. Podobnie jak udziały czasu, sprawia, że czujesz, że działają równolegle, ale ich egzekucje są przeplatane, a nie nakładające się. Jeśli jest związany z IO, tak, osiąga równoległy sprzęt (urządzenia IO), a nie kod.
b. różnica z wywołaniem funkcji?
Jak pokazuje zdjęcie, nie trzeba dzwonić, return
aby przełączyć kontrolę. Może ulec bez return
. Korpus zapisuje i współdzieli stan w bieżącej ramce funkcji (stosie). Jest więc znacznie lżejszy niż funkcja, ponieważ nie trzeba zapisywać rejestrów i zmiennych lokalnych, aby układać stosy i przewijać stos wywołań call ret
.
Rozwinę odpowiedź @ @ user21714. Korpusy są niezależnymi ścieżkami wykonania, które nie mogą działać jednocześnie. Zależą od kontrolera - na przykład python
biblioteki kontrolera - do obsługi przełączania między tymi ścieżkami. Ale żeby to zadziałało, same korporacje muszą się przywołaćyield
lub podobne struktury, które pozwalają na wstrzymanie ich wykonywania.
Wątki zamiast tego działają na niezależnych zasobach obliczeniowych i równolegle ze sobą. Ponieważ znajdują się na różnych zasobach, nie ma potrzeby wywoływania dochodu, aby umożliwić kontynuowanie innych ścieżek wykonania.
Możesz zobaczyć ten efekt, uruchamiając program wielowątkowy - np. jvm
Aplikację - w której wykorzystuje się wszystkie osiem core i7
rdzeni hiperwątkowych: możesz zobaczyć 797% wykorzystania w Activity Monitor
lub Top
. Zamiast tego podczas uruchamiania typowego python
programu - nawet takiego z coroutines
lub python threading
- wykorzystanie będzie maksymalne na 100%. Tj. Jeden wątek maszyny.