プログラマーの Python Async – プロセス ベースの並列処理

1/3 ページ

asynco モジュールは町で最もホットなトピックかもしれませんが、知る価値のある Python の唯一の非同期機能ではありません。 私の新しい本からのこの抜粋で、プロセスベースの並列処理について調べてください プログラマーの Python: 非同期 – GILの問題がないという利点があります。

プログラマーの Python:
非同期
スレッド、プロセス、非同期など

印刷本として入手可能になりました:Amazon

コンテンツ

1) Python のライトニング ツアー

Python の起源、基本的な Python、データ構造、制御構造 – ループ、スペースの問題、条件とインデント、パターン マッチング、すべてがオブジェクト – 参照、関数、オブジェクトとクラス、継承、メインとモジュール、Python の IDE、Pythonic – Theメタ哲学、次の場所、要約。

2) 非同期の説明

シングルスレッド、 プロセス、 I/O バウンドおよび CPU バウンド、スレッド、ロック、デッドロック、複数のスレッドを使用するプロセス、シングル スレッドの非同期、イベント、イベントまたはスレッド、コールバック ヘル、複数の CPU – 同時実行、概要。

3) 処理ベースの並列処理

抽出 1 – プロセス ベースの並列処理

プロセス クラス、デーモン、プロセスの待機、最初のプロセスの完了の待機、Pi の計算、Fork v Spawn、Forkserve、開始方法の制御、概要。

4) スレッド

スレッド クラス、スレッドと GIL、スレッド ユーティリティ、デーモン スレッド、スレッドの待機、ローカル変数、スレッド ローカル ストレージ、複数のスレッドによる Pi の計算、I/O バウンド スレッド、Sleep(0)、タイマー オブジェクト、概要。

5) ロックとデッドロック

競合状態、ハードウェアの問題または Heisenbug、ロック、ロックとプロセス、デッドロック、コンテキスト管理ロック、再帰ロック、セマフォ、アトミック操作、アトミック CPython、ロックフリー コード、ロックを使用した Pi の計算、概要。

6) 同期

結合、最初から最後まで、イベント、バリア、条件オブジェクト、普遍的な条件オブジェクト、概要。

7) データの共有

キュー、パイプ、スレッドのキュー、共有メモリ、共有 ctypes、Raw 共有メモリ、共有メモリ、マネージャー、コンピューティング Pi 、概要。

8) プロセスプール

プール プロセスの待機、AsyncResult を使用した Pi の計算、Map_async、Starmap_async、即時結果 – imap、MapReduce、共有とロック、概要。

9) プロセスマネージャー

SyncManager、プロキシの仕組み、ロック、マネージャーを使用した Pi の計算、カスタム マネージャー、カスタム データ タイプ、BaseProxy、プロパティ プロキシ、リモート マネージャー、リモート プロシージャ コール、最終的な考え、まとめ。

10) サブプロセス

プログラムの実行、入力/出力、Popen、相互作用、ノンブロッキング読み取りパイプ、サブプロセスの使用、概要。

11) 先物

Futures、Executors、I/O-Bound の例、Future の待機、Future Done コールバック、例外の処理、データのロックと共有、パラメーターのロックとプロセス、初期化子を使用した共有グローバルの作成、プロセス マネージャーを使用したリソースの共有、Future の共有およびデッドロック、先物、プロセス プールまたは同時先物を使用した Pi の計算、概要。

12) 基本非同期

抽出 1 基本非同期

コールバック、Future と Await、コルーチン、Await、Awaiting Sleep、タスク、実行順序、タスクと Future、コルーチンの待機、シーケンシャルとコンカレント、タスクのキャンセル、例外の処理、共有変数とロック、コンテキスト変数、キュー、概要。

13) asyncio の使用

ストリーム、Web ページのダウンロード、サーバー、Web サーバー、SSL サーバー、ストリームの使用、ブロッキングからノンブロッキングへの変換、スレッドでの実行、スレッドを使用しない理由、CPU バウンド タスク、非同期ベースのモジュール、他のイベントの操作ループ – Tkinter、サブプロセス、概要。

14) 低レベル API

抽出 1 – ストリームと Web クライアント

イベント ループ、ループの使用、プロセスでのタスクの実行、asyncio を使用した Pi の計算、ネットワーク関数、
トランスポートとプロトコル、UDP サーバー、UDP クライアント、ブロードキャスト UDP、ソケット、イベント ループの実装、適切な非同期操作の条件、概要。

付録 I Visual Studio Code での Python

非同期プログラミングに関するほとんどの本は、スレッドを調べることから始めます。スレッドは一般に、実行のビルディング ブロックと見なされているからです。 ただし、Python の場合、デフォルトで単一の実行スレッドが付属するプロセスから開始することには利点があります。 理由は、一般的なものと具体的なものの両方です。 プロセスは互いに分離されているため、ロックの問題が少なくなります。

また、Python にはグローバル インタープリター ロックまたは GIL と呼ばれるスレッドの実行方法に関する制限があり、特定の時間に 1 つのスレッドのみが Python システムを実行できるという事実もあります。 これは、多大な努力がなければ、複数のスレッドが複数のコアを利用できないため、高速化の方法を提供しないことを意味します。 スレッドと GIL については次の章でさらに詳しく説明しますが、現時点で知っておく必要があるのは、プロセスが複数のコアを使用することでプログラムを高速化できるということだけです。 Python スレッドを使用すると、真の並列処理を実現できませんが、プロセスを使用すると実現できます。

これが意味することは、I/O バウンド タスクがある場合、I/O バウンド スレッドが停止しているときにプロセッサが別のスレッドを処理できるため、スレッドを使用すると速度が向上するということです。 CPU バウンドのタスクがある場合は、プロセスの並列化以外に何も役に立ちません。

プロセス クラス

プロセスを操作する際の重要なアイデアは、最初の Python プログラムを独自のプロセスで開始し、マルチプロセッシング モジュールの Process クラスを使用してサブプロセスを作成できるということです。 子プロセスは、Python 用語では、親プロセスによって作成および制御されます。 最も単純な例を見てみましょう。

import multiprocessing
def myProcess():
    print("Hello Process World")
if __name__ == '__main__':
    p1=multiprocessing.Process(target=myProcess)
    p1.start()

この場合、ターゲットを myProcess 関数オブジェクトに設定して Process オブジェクトを作成するだけです。 start メソッドを呼び出すと、新しいプロセスが作成され、myProcess を呼び出してコードの実行が開始されます。 Hello Process World が表示されるだけです。

ここでは新しいことはほとんどないように見えますが、明らかではない多くのことが進行中です。 start メソッドを呼び出すと、まったく新しいプロセスが作成され、Python インタープリターと Python プログラムの新しいコピーが完成します。 Python プログラムが新しいプロセスにどのように提供されるかは、それを実行しているシステムによって異なります。これは後で説明する微妙な点です。

プロセス1

今のところ、3 つの単純なルールに従う必要があります。

  1. 常に if __name__ == ‘__main__’: を使用して、セットアップ コードが子プロセスで実行されないようにします。

  2. グローバル リソースは子プロセスで常に使用できるとは限らないため、セットアップ コードでグローバル リソースを定義または変更しないでください。

  3. グローバル定数ではなく、パラメーターを使用して子プロセスに初期データを渡すことをお勧めします。

これらのルールの理由については、後で詳しく説明します。

一般に、新しいプロセスを作成して実行するには、次を使用して Process オブジェクトを作成する必要があります。

class multiprocessing.Process(group=None, target=None, 
            name=None, args=(), kwargs={}, daemon=None)

group パラメーターは、次の章でスレッドを作成する呼び出しと同じ呼び出しを行うために含まれているだけなので、無視できます。 ターゲットは、新しいプロセスを実行する呼び出し可能オブジェクトであり、名前は新しいプロセスに適用されるものです。 名前を指定しない場合は、一意の名前が作成されます。 最も重要なパラメーターは、callable に渡す位置パラメーターとキーワード パラメーターを指定する args と kwargs です。

例えば:

p1=multiprocessing.Process(target=myProcess,(42,43),
{“myParam1”:44})

ターゲットを次のように呼び出します。

myProcess(42,43,myParam1=44)

Process オブジェクトには、start メソッドに加えて、多くの便利なメソッドと属性があります。 これらの中で最も単純なものは name と pid です。

name 属性を使用して、子プロセスに割り当てられた名前を見つけることができます。 オペレーティングシステムがそれについて何も知らないという意味では、それ以上の意味はありません。 一方、pid 属性は、オペレーティング システムによって割り当てられるプロセス ID 番号であり、kill などのオペレーティング システム コマンドを介して子プロセスを処理するために使用する pid です。

name 属性と pid 属性の両方がプロセスの識別に役立ちますが、セキュリティ上の理由から authkey 属性を使用する必要があります。 これは、マルチプロセッシング モジュールのロード時に乱数に設定され、子プロセスの安全な識別子として機能することを目的としています。 各 Process オブジェクトには親プロセスの authkey 値が与えられ、これを使用して、プロセスが実際に親プロセスの子プロセスであることを証明できます。これについては後で詳しく説明します。

multiprocessing モジュールには、子プロセスが実行されている環境を調べるために使用できるいくつかのメソッドも含まれています。

  • multiprocessing.cpu_count() は、システム内の CPU、つまりコアの数を示します。 これは、並行して実行できるプロセスの理論上の最大数です。 実際には、利用可能な最大数は通常これより少なくなります。

  • multiprocessing.cpu_set_executable() は、子プロセスに使用する Python インタープリターの場所を提供します。

Python プロセスは基本的なネイティブ プロセスではありません。 親プロセスで定義された Python コードとともに Python インタープリターが読み込まれ、ターゲットとして渡された関数を実行する準備が整います。

.

Leave a Comment

Your email address will not be published. Required fields are marked *