Python でのコルーチンと並行性の用途は何ですか?

青灯夜游
リリース: 2018-09-21 15:19:55
オリジナル
2583 人が閲覧しました

この章では、Python におけるコルーチンの役割と同時実行性について紹介し、コルーチン使用の長所と短所、および gevent 同時実行フレームワークの役割を理解できるようにします。一定の参考値があるので、困っている友達は参考にしていただければ幸いです。

Coroutine

Coroutine はユーザー モードの軽量スレッドであり、マイクロスレッドとも呼ばれます。

コルーチンには独自のレジスタ コンテキストとスタックがあります。スケジュールを切り替えると、レジスタ コンテキストとスタックは別の場所に保存されます。切り替えを戻すと、以前に保存したレジスタ コンテキストとスタックが復元されます。したがって、コルーチンは最後の呼び出しの状態 (つまり、すべてのローカル状態の特定の組み合わせ) を保持できます。プロセスが再入するたびに、最後の呼び出しの状態に入ることと同じになります。前回終了時の状態 論理フローの場所

利点:

  1. スレッド コンテキスト切り替えのオーバーヘッドなし

  2. アトミック操作のロックと同期のオーバーヘッドなし

  3. 制御フローを簡単に切り替え、プログラミング モデルを簡素化します

  4. 高い同時実行性、高いスケーラビリティ、低コスト: CPU が数十のプロセッサをサポートすることは問題ではありません。何千ものコルーチン。したがって、高度な同時処理に非常に適しています。

いわゆるアトミック操作は、スレッド スケジューリング メカニズムによって中断されない操作を指します。この操作は、一度開始されると、コンテキスト スイッチ (スイッチ) なしで最後まで実行されます。別のスレッドへ)。

アトミック操作は 1 ステップまたは複数ステップで行うことができますが、順序を崩したり、実行された部分のみを切断したりすることはできません。全体として見ることが原子性の核心です。

欠点:

  1. マルチコアリソースを利用できない: コルーチンの本質はシングルスレッドであり、単一の CPU の複数のコアを同時に使用することはできません。コルーチンは、複数の CPU で実行するにはプロセスが連携する必要があります。もちろん、私たちが日常的に作成するアプリケーションのほとんどは、CPU を大量に使用するアプリケーションでない限り、この必要性はありません。

  2. ブロッキング操作 (IO など) を実行すると、プログラム全体がブロックされます

Gevent を使用します

gevent は Python の同時実行フレームワークであり、コアとしてマイクロスレッド Greenlet を備え、epoll イベント リスニング メカニズムやその他の多くの最適化を使用して効率化しています。:

  • 簡単な例

gevent のスリープは制御を引き継ぐことができます。ネットワークまたは IO によって制限されている関数で gevent を使用すると、これらの関数は協調的にスケジュールされます。gevent の真の機能は次のとおりです。解き放たれた。 Gevent はすべての詳細を処理して、可能な場合にはネットワーク ライブラリが暗黙的に実行権限を greenlet コンテキストに引き渡すようにします。

import gevent
 
def foo():
    print('running in foo')
    gevent.sleep(0)
    print('com back from bar in to foo')
 
def bar():
    print('running in bar')
    gevent.sleep(0)
    print('com back from foo in to bar')
 
# 创建线程并行执行程序
gevent.joinall([
    gevent.spawn(foo),
    gevent.spawn(bar),
])
ログイン後にコピー

実行結果:

Python でのコルーチンと並行性の用途は何ですか?

  • 同期非同期

import random
import gevent
 
def task(pid):
    gevent.sleep(random.randint(0, 2) * 0.001)
    print('Task %s done' % pid)
 
def synchronous():
    for i in range(1, 10):
        task(i)
 
def asynchronous():
    threads = [gevent.spawn(task, i) for i in range(10)]
    gevent.joinall(threads)
 
print('Synchronous:')
synchronous()
 
print('Asynchronous:')
asynchronous()
ログイン後にコピー

実行出力:

Python でのコルーチンと並行性の用途は何ですか?

  • #サブクラス メソッドでのコルーチンの使用

  • ##Greenlet クラスをサブクラス化できます。 _run メソッド (マルチスレッドおよびマルチプロセス モジュールと同様)
import gevent
from gevent import Greenlet
 
class Test(Greenlet):
 
    def __init__(self, message, n):
        Greenlet.__init__(self)
        self.message = message
        self.n = n
 
    def _run(self):
        print(self.message, 'start')
        gevent.sleep(self.n)
        print(self.message, 'end')
 
tests = [
    Test("hello", 3),
    Test("world", 2),
]
 
for test in tests:
    test.start()  # 启动
 
for test in tests:
    test.join()  # 等待执行结束
ログイン後にコピー

    モンキー パッチを使用してシステム標準ライブラリを変更します (コルーチンを自動的に切り替えます)
  • グリーンレットがネットワークへのアクセスなどのIO操作に遭遇すると、自動的に他のグリーンレットに切り替わり、IO操作が完了するまで待機し、適切なタイミングで元に戻って実行を継続します。

IO 操作は非常に時間がかかるため、プログラムは待機状態になることがよくありますが、gevent がコルーチンを自動的に切り替えることで、Greenlet が IO を待機するのではなく常に実行されることが保証されます。

切り替えは IO 操作中に自動的に完了するため、gevent は Python に付属する標準ライブラリの一部を変更する必要があります。このプロセスは起動時のモンキー パッチによって完了します。

import gevent
import requests
from gevent import monkey
 
monkey.patch_socket()
 
def task(url):
    r = requests.get(url)
    print('%s bytes received from %s' % (len(r.text), url))
 
gevent.joinall([
    gevent.spawn(task, 'https://www.baidu.com/'),
    gevent.spawn(task, 'https://www.qq.com/'),
    gevent.spawn(task, 'https://www.jd.com/'),
])
ログイン後にコピー

実行出力:


Python でのコルーチンと並行性の用途は何ですか?3 つのネットワーク操作が同時に実行され、終了順序が異なることがわかります。

以上がPython でのコルーチンと並行性の用途は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート