コルーチンとは何ですか?


204

コルーチンとは何ですか?それらは並行性とどのように関連していますか?


2
並行コードは必ずしも「並列」で実行する必要はありません(新しい用語を導入しないでください)。
lucid_dreamer 2018年

2
Linux、BSD、およびWindows用のselect / poll / eplll / kqueue / iocp / Win GUIメッセージをサポートする、標準Cのコルーチンライブラリを1つ作成しました。これはgithub.com/acl-dev/libfiberのオープンソースプロジェクトです。助言はうまくいきます。
ShuXin Zheng 2018

ここでさらに興味深い情報:stackoverflow.com/q/16951904/14357
18

この時代に問われた場合、この質問は反対投票になると思います。以前と比べてコミュニティの認識にこのように大きな違いがあるのはなぜですか?
tnkh

コルーチンがリターンに到達する前にその実行を一時停止することができます関数であり、それは間接的にいくつかの時間のために別のコルーチンに制御を渡すことができます。
hassanzadeh.sd

回答:


138

コルーチンと並行性はほぼ直交しています。コルーチンは、フロー制御が戻ることなく2つの異なるルーチン間で協調的に渡される一般的な制御構造です。

Pythonの「yield」ステートメントが良い例です。コルーチンを作成します。「yield」が発生すると、関数の現在の状態が保存され、制御は呼び出し元の関数に戻ります。呼び出し元の関数は、実行を譲る関数に戻すことができ、その状態は「降伏」に遭遇したポイントに復元され、実行が続行されます。


19
関数を直接呼び出すことと、この関数をこのコルーチンにラップしてコルーチンから生成することの違いは何ですか?
Ming Li

3
その場合、これらの2つの概念は、このコンテキストでは実際には「直交」ではないことを説明するほうがよいでしょう。2つの概念が互いにどのように類似しているかを明確に描くことができます。2つ以上のものの間で制御を渡すという考え方は非常に似ています。
steviejay 2017

8
Coroutines are a general control structure whereby flow control is cooperatively passed between two different routines without returning.<-これ同時実行です。あなたが探している言葉は並列性です。
Adam Arold

@steviejay orthogonal = Not similar to each other
tonix

1
@tonix orthogonal「お互いに独立している」という意味だと言われました。
リック

77

以下からのLuaでのプログラミングCoroutinesセクション」:

コルーチンはスレッド(マルチスレッドの意味で)に似ています。これは、独自のスタック、独自のローカル変数、および独自の命令ポインターを持つ実行行です。しかし、それはグローバル変数と他のコルーチンとほとんど何でも共有します。スレッドとコルーチンの主な違いは、概念的に(または文字通り、マルチプロセッサマシンでは)スレッドを含むプログラムが複数のスレッドを並行して実行することです。一方、コルーチンは協調的です。コルーチンを含むプログラムは常にコルーチンの1つだけを実行しており、この実行中のコルーチンは、明示的に中断するように要求した場合にのみ実行を中断します。

つまり、コルーチンは「協調的」です。マルチコアシステムでも、コルーチンは常に1つしか実行されません(ただし、複数のスレッドを並行して実行できます)。コルーチン間には非プリエンプティブがあり、実行中のコルーチンは実行を明示的に放棄する必要があります。

concurrency」については、Rob Pikeのスライドを参照してください。

並行性は、独立して実行される計算の構成です。

したがって、コルーチンAの実行中に、コルーチンBに制御が渡されます。しばらくすると、コルーチンBはコルーチンAに制御を戻します。コルーチン間に依存関係があるため、コルーチンはタンデムで実行する必要があるため、2つのコルーチンは並行性ではありません


6
コルーチンは独立して実行されません。彼らは交代で、お互いが仕事の一部を行うのを待っています。彼らは積極的にお互いに調整します。これは、同時実行性のロブパイクスの定義の反対です。
エリックG.ハグストロム2016年

2
@ ErickG.Hagstrom:独立して実行されるわけではありませんが、すべてのコルーチンのロジックは独立することができますよね?それが正しければ、1コアCPUで実行されているプリエンプティブでないOSのように、1つのプロセスがCPUを解放して他のタスクを実行できるようにする必要があります。
Nan Xiao

6
他のタスクを実行するためにCPUを解放することと、実行する時が来ていることを特定の他のプロセスに伝えることとの間には違いがあります。コルーチンは後者を行います。それはある意味で独立したものではありません。
エリックG.ハグストロム

7
@ChrisClark同意します。コルーチンは同時実行です。以下はウィキペディアの引用です。コルーチンはスレッドに非常に似ています。ただし、コルーチンは協調的にマルチタスク処理されますが、スレッドは通常プリエンプティブにマルチタスク処理されます。つまり、並行性は提供されますが、並列性は提供されません
smwikipedia 2018年

3
And:協調マルチタスクは、非プリエンプティブマルチタスクとも呼ばれ、オペレーティングシステムが実行中のプロセスから別のプロセスへのコンテキストスイッチを開始しないスタイルのコンピューターマルチタスクです。代わりに、複数のアプリケーションを同時に実行できるようにするために、プロセスは定期的に、またはアイドル状態または論理的にブロックされたときに自発的に制御を譲ります。
smwikipedia 2018年

47

技術的な質問ですが、ほとんどの回答が技術的すぎると思います。コルーチンのプロセスを理解するのに苦労しました。ちょっとわかりますが、同時にはわかりません。

私はここでこの答えが非常に役に立ったと感じました:

https://dev.to/thibmaek/explain-coroutines-like-im-five-2d9

Idan Aryeから引用するには:

あなたのストーリーに基づいて、私はそれをこのようなものにしたいと思います:

あなたは漫画を見始めますが、それはイントロです。イントロを見る代わりに、ゲームに切り替えてオンラインロビーに入ります。ただし、3人のプレーヤーが必要で、あなたとあなたの姉妹だけがそこにいます。他のプレイヤーが参加するのを待つ代わりに、宿題に切り替えて、最初の質問に答えます。2番目の質問には、視聴する必要のあるYouTubeビデオへのリンクがあります。あなたはそれを開きます-そしてそれはロードを開始します。読み込まれるのを待つのではなく、漫画に切り替えます。イントロが終わったので視聴できます。これでコマーシャルができました-一方で、3人目のプレイヤーが参加したので、ゲームに切り替えました。

考えは、タスクを本当に速く切り替えるだけではなく、一度にすべてを実行しているように見せることです。あなたは何かが起こるのを待っている時間(IO)を利用して、あなたの直接の注意を必要とする他のことをします。

確実にリンクを確認してください。私がすべてを引用することはできません。


6
非常にシンプルでわかりやすいイラスト。+1。
Taslim Oseni

素晴らしいイラスト。私は同様の物語を作りました-荷物を集めるのを待って並んでいます。しかし、今日のあなたの方がはるかに現実的です。door2doorの配達があるときに誰が並ぶのでしょうか。Lol
アポラック

1
それは素晴らしい説明です。引用自体から、それは非常に明確です。
Farruh Habibullaev

15

コルーチンは、サブルーチン/スレッドに似ています。違いは、呼び出し元がサブルーチン/スレッドを呼び出すと、呼び出し元の関数に戻らないことです。ただし、いくつかのコードを実行した後、コルーチンは呼び出し元に戻って、呼び出し元が独自のコードの一部を実行し、コルーチンポイントに戻って実行を停止し、そこから続行することができます。すなわち。コルーチンには複数の入口と出口があります


これは、独立して同時に実行されるスレッド(分離したコアを並列に)にそれほど似ていません。さらに、複数の独立した実行パスがあり、それらが互いに結果を返さないという意味で、サブルーチンの比較は失敗します。
javadba

11
  • コルーチンはKotlin言語で利用できる優れた機能です
  • コルーチンは、非同期の非ブロッキングコード(およびその他)を記述する新しい方法です
  • コルーチンは軽量スレッドです。軽量スレッドは、ネイティブスレッドにマップしないことを意味します。そのため、プロセッサでコンテキストを切り替える必要がなく、高速です。
  • ネイティブスレッドにマップされません
  • コルーチンとスレッドはどちらもマルチタスクです。ただし、違いは、スレッドはOSによって管理され、コルーチンはユーザーによって管理されることです。

基本的に、コルーチンには2つのタイプがあります。

  1. スタックレス
  2. スタックフル

Kotlinはスタックレスコルーチンを実装しています。つまり、コルーチンには独自のスタックがないため、ネイティブスレッドにマップされません。

これらはコルーチンを開始する関数です:

launch{}

async{}

あなたはここからもっと学ぶことができます:

https://www.kotlindevelopment.com/deep-dive-coroutines/

https://blog.mindorks.com/what-are-coroutines-in-kotlin-bf4fecd476e9


1
いい答えだ!KotlinおよびAndroid開発者に役立ちます。
Malwinder Singh

5

別の言い方をすると、Python geventライブラリには、coroutine非同期ネットワーク要求などのスレッドのような機能を提供するベースのネットワークライブラリがあり、スレッドの作成と破棄のオーバーヘッドがありません。coroutine使用するライブラリですgreenlet


2

Pythonコルーチンから:

Pythonコルーチンの実行は、多くの時点で一時停止および再開できます(コルーチンを参照)。コルーチン関数の本体内で、awaitおよびasync識別子は予約済みキーワードになります。await式、async forおよびasync withは、コルーチン関数本体でのみ使用できます。

コルーチンから(C ++ 20)

コルーチンは、実行を一時停止して 後で再開できる機能です。コルーチンはスタックレスです。呼び出し側に戻って実行を一時停止します。これにより、非同期で実行されるシーケンシャルコードが可能になり(明示的なコールバックなしで非ブロッキングI / Oを処理するなど)、遅延計算された無限シーケンスやその他の使用に関するアルゴリズムもサポートされます。

他の人の答えと比較してください:

私の意見では、再開された後の部分は、@ Twinkleと同様に、コアの違いです。
ドキュメントの多くのフィールドはまだ進行中ですが、この部分は@Nan Xiaoを除いてほとんどの回答と似ています

一方、コルーチンは協調的です。コルーチンを含むプログラムは常にコルーチンの1つだけを実行しており、この実行中のコルーチンは、明示的に中断するように要求した場合にのみ実行を中断します。

LuaのProgramから引用されているため、多分それは言語に関連している(現時点ではLuaに精通していない)、すべてのドキュメントが1つの部分のみについて言及しているわけではありません。

コンカレントとの関係:コルーチン(C ++ 20)の
「実行」部分があります。ここで引用するには長すぎます。 詳細の他に、いくつかの状態があります。

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 

@ user217714の回答の下の@Adam Aroldからのコメントとして。それは並行性です。
しかし、それはマルチスレッドとは異なります。 std :: threadから

スレッドを使用すると、複数の関数を同時に実行できます。スレッドは、関連するスレッドオブジェクトが構築されるとすぐに実行を開始し(OSスケジューリング遅延が保留中)、コンストラクター引数として提供されるトップレベルの関数から始まります。トップレベル関数の戻り値は無視され、例外がスローされて終了した場合は、std :: terminateが呼び出されます。トップレベル関数は、std :: promiseを介して、または共有変数を変更することによって、戻り値または例外を呼び出し元に通知する場合があります(同期が必要な場合があります。std:: mutexおよびstd :: atomicを参照してください)。

並行性であるため、特に(OSの観点から)待機が避けられない場合はマルチスレッドのように機能し、それが混乱を招く理由でもあります。


1

コルーチンは特別な種類のサブプログラムです。従来のサブプログラムに存在する、呼び出し元と呼び出されたサブプログラム間のマスタースレーブ関係ではなく、呼び出し元と呼び出されたコルーチンはより公平です。

  • コルーチンは、複数のエントリを持ち、それら自体を制御するサブプログラムです。Luaで直接サポートされています

  • 対称制御とも呼ばれます:呼び出し元と呼び出されたコルーチンはより同等に基づいています

  • コルーチンの呼び出しは履歴書と呼ばれます

  • コルーチンの最初の再開は最初ですが、後続の呼び出しは、コルーチンで最後に実行されたステートメントの直後の時点で開始されます

  • コルーチンは繰り返し、おそらくは永遠に互いに再開します

  • コルーチンは、プログラム単位(コルーチン)の準並行実行を提供します。それらの実行はインターリーブされますが、オーバーラップされません

例1 例2


1

このリンクからの説明は非常に簡単です。これらの回答はいずれも、この回答の最後の箇条書きを除いて、同時実行性と並列性を説明するものではありません。

  1. 並行(プログラム)とは何ですか?

伝説的なジョーアームストロングによる「プログラミングアーラン」からの引用

並行プログラムは、並列コンピューター上で潜在的に高速に実行できます。

  • 並行プログラムは、並行プログラミング言語で書かれたプログラムです。パフォーマンス、スケーラビリティ、またはフォールトトレランスの理由から、並行プログラムを作成します。

  • 並行プログラミング言語は、並行プログラムを作成するための明示的な言語構造を持つ言語です。これらの構成要素はプログラミング言語の不可欠な部分であり、すべてのオペレーティングシステムで同じように動作します。

  • 並列コンピューターは、同時に実行できる複数の処理ユニット(CPUまたはコア)を持つコンピューターです。

したがって、並行性は並列処理と同じではありません。シングルコアコンピューターで並行プログラムを作成することもできます。タイムシェアリングスケジューラは、プログラムが同時に実行されていると感じさせます。

並行プログラムは、並列コンピューターで並列に実行される可能性がありますが、保証されてません。OSは、プログラムを実行するためのコアを1つだけ提供する場合があります。

したがって、並行性は並行プログラムのソフトウェアモデルであり、プログラムが物理的に並列実行できることを意味しません。

  1. コルーチンと並行性

「コルーチン」という単語は、「co」(協調的)と「ルーチン」(関数)の2つの単語で構成されています。

a。それは並行性または並列性を実現しますか?

簡単にするために、シングルコアコンピュータでそれを説明しましょう。

並行性は、OSからのタイムシェアリングによって実現されます。スレッドは、CPUコアの割り当てられたタイムフレームでコードを実行します。OSによってプリエンプトできます。また、OSを制御する可能性もあります。

一方、コルーチンは、OSではなく、スレッド内の別のコルーチンに制御を渡します。したがって、スレッド内のすべてのコルーチンは、OSが管理する他のスレッドにCPUコアを譲らずに、そのスレッドのタイムフレームを利用します。

したがって、コルーチンは、OS(または準並列処理)ではなく、ユーザーがタイムシェアを実現すると考えることができます。コルーチンは、それらのコルーチンを実行するスレッドに割り当てられた同じコアで実行されます。

コルーチンは並列処理を実現しますか?CPUにバインドされたコードの場合、違います。タイムシェアのように、それらは並列に実行されているように感じますが、それらの実行はオーバーラップされずにインターリーブされます。IOバウンドの場合、はい、コードではなくハードウェア(IOデバイス)によって並列処理を実現します。

b。関数呼び出しとの違いは?

ここに画像の説明を入力してください

写真が示すように、returnコントロールを切り替えるために呼び出す必要はありません。それなしで譲ることができreturnます。コルーチンは、現在の関数フレーム(スタック)の状態を保存して共有します。したがって、の際に呼び出しスタックをスタックして巻き戻すためにレジスタとローカル変数を保存する必要がないため、関数よりもはるかに軽量ですcall ret


0

@ user21714の答えを詳しく説明します。コルーチンは、同時に実行できない独立した実行パスです。これらは、pythonこれらのパス間の切り替えを処理するために、コントローラー(コントローラーライブラリなど)に依存しています。しかし、これが機能するためには、コルーチン自体がyield、実行を一時停止できるようにする呼び出しまたは同様の構造を実行する必要があります。

代わりに、スレッドは独立したコンピューティングリソース上で実行され、互いに並行して実行されます。それらは異なるリソース上にあるため、yieldを呼び出して他の実行パスを続行できるようにする必要はありません。

あなたはmultihreadedプログラムを起動することによってこの効果を見ることができます-例えばjvmアプリケーション-あなたの全8れるcore i7ハイパースレッドコアが利用されている:あなたは797%の使用率が表示されることがありますActivity MonitorTop。代わりに、典型的なpythonプログラムを実行しているとき- coroutinesまたはpython threading-を使用している場合でも、使用率は100%で最大になります。つまり、1つのマシンのハイパースレッドです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.