web-dev-qa-db-ja.com

Python:スレッドに対する非同期の利点は何ですか?

pythonで非同期機能がどのように、どのように機能するかを理解するのに苦労しましたが、まだすべてを正しく理解できません(特に「理由」部分)。私は間違っています。

非同期メソッドとスレッドの両方の目的は、複数のタスクを同時に処理できるようにすることです。

スレッドアプローチはシンプルで直感的に見えます。 pythonプログラムが複数のタスクを同時に処理する場合、タスクごとにスレッド(サブスレッドを含む)がある場合、各スレッドのスタックは、対応するタスクの処理の現在の段階を反映します。 、新しいスレッドを開始し、その結果を待つための使いやすいメカニズムがあります。

私が理解しているように、このアプローチの唯一の問題は、スレッドが高価であることです。

別のアプローチは、asyncコルーチンを使用することです。このアプローチにはいくつかの不便さがあります。私はそれらのカップルだけに名前を付けます。現在、通常のメソッドとasyncメソッドの2種類のメソッドがあります。唯一の違いは、このメソッドがasyncであることを覚えておく必要があることと、このメソッドを呼び出すときにawaitキーワードを使用することを忘れないことです。はい、通常のメソッドからasyncメソッドを呼び出すことはできません。そして、プログラム全体のこのすべてのasync-await構文上のゴミは、このメソッドがメッセージループに制御を渡すことができることを示すためだけのものです。

スレッドアプローチには、これらのすべての不便はありません。ただし、async-awaitアプローチでは、スレッドアプローチよりもはるかに多くの同時タスクを処理できます。そんなことがあるものか?

並行タスクごとにまだコールスタックがありますが、現在はコルーチンコールスタックです。確かではありませんが、これが重要な違いのようです:通常のスタックはオペレーティングシステムスタックであり、高価であり、コルーチンスタックはpython構造体であり、はるかに安価です。これは私の理解が正しいですか?

これが正しければ、pythonスレッド/コールスタックをOSスレッド/コールスタックから分離して、pythonスレッドを安くする方が良いでしょうか?

この質問が愚かであれば申し訳ありません。 async-awaitアプローチが選択された理由はいくつかあると確信しています。これらの理由を理解したいだけです。

更新:

この質問は良くない、広すぎると思わない人のために。

ここに記事があります nyielding -スレッドが悪い理由の説明から始まり、asyncアプローチを広告します。主な論文:スレッドは悪であり、任意の数のスレッドから同時に実行される可能性のあるルーチンについて推論するのは非常に困難です。

このリンクを提案してくれたNathaniel J. Smith(python Trio library)の著者)に感謝します。

ところで、この記事の議論は私には納得できませんが、それでも役に立つかもしれません。

12
lesnik

この記事 質問に答えます。

TL; DR?

Python=のスレッド化は、複数のスレッドを並行して実行できないことを意味する [〜#〜] gil [〜#〜] (グローバルインタープリターロック)のために非効率的です。マルチプロセッサシステムで予想されるように、スレッド間の切り替えにはインタプリタに依存する必要があるため、非効率性が増します。

asyc/ asyncio は、単一のスレッド内で並行性を許可します。これにより、開発者はタスク切り替えをよりきめ細かく制御でき、同時I/OバウンドタスクのパフォーマンスはPythonスレッド化よりもはるかに優れています。

言及していない3番目のアプローチは、 multiprocessing です。このアプローチでは、並行性のためにプロセスを使用し、プログラムが複数のコアを持つハードウェアを最大限に活用できるようにします。

2
Luke Smith

Asyncioはまったく異なる世界であり、知る限りでは、開始以来このことを行うnode.jsに対するpythonの答えです。例えば。 asyncioの状態に関するthis official python doc

非同期プログラミングは、従来の「シーケンシャル」プログラミングとは異なります

だから、あなたはそのウサギの穴に飛び込んでこの用語を学ぶかどうかを決める必要があります。ネットワークまたはディスク関連の重いタスクに直面している場合にのみ、おそらく理にかなっています。もしそうなら この記事 は、python 3のasyncioがnode.jsよりも速く、Goのパフォーマンスに近いと主張しています。

つまり、まだasyncioを使用していないので、これについて本当にコメントすることはできませんが、あなたの質問からいくつかの文章にコメントすることができます。

そして、このすべての非同期-プログラム全体の構文上のゴミを待つことは、このメソッドがメッセージループに制御を渡すことができることを示すことだけです

私が見る限り、あなたはasyncioの初期セットアップを持っていますが、すべての呼び出しは、あなたがstart()join()する必要があるスレッドで同じことをするよりも構文が少ないですまた、おそらくis_alive()で確認し、戻り値を取得するには、まず共有オブジェクトを設定する必要があります。そのため、いいえ、asyncioは見た目が異なりますが、最終的にはプログラムはスレッドを使用した場合よりもきれいになります。

私が理解しているように、このアプローチの唯一の問題は、スレッドが高価であることです

あんまり。新しいスレッドを開始するのは非常に安価で、CまたはJavaで「ネイティブスレッド」を開始するのと同じコストがかかります

これは重要な違いのように見えます:通常のスタックはオペレーティングシステムのスタックであり、高価であり、コルーチンのスタックはpython構造体であり、はるかに安価です。これは私の理解ですか?

あんまり。 OSレベルのスレッドの作成に勝るものはありません。安価です。 asyncioの優れている点は、必要なスレッドスイッチが少ないことです。したがって、ネットワークまたはディスクを待機している多数の並行スレッドがある場合、asyncioはおそらく速度を上げるでしょう。

1
hansaplast