相互通信を処理します
プロセス相互通信とは、プロセス間のデータ交換を意味します。並列アプリケーションの開発には、プロセス間でデータを交換する必要があります。次の図は、複数のサブプロセス間の同期のためのさまざまな通信メカニズムを示しています。
さまざまな通信メカニズム
このセクションでは、さまざまな通信メカニズムについて学習します。メカニズムは以下のとおりです-
キュー
キューは、マルチプロセスプログラムで使用できます。のキュークラスmultiprocessing モジュールはに似ています Queue.Queueクラス。したがって、同じAPIを使用できます。Multiprocessing.Queueは、プロセス間の通信のスレッドおよびプロセスセーフFIFO(先入れ先出し)メカニズムを提供します。
例
以下は、マルチプロセッシングのQueueクラスの概念を理解するために、マルチプロセッシングに関するPythonの公式ドキュメントから抜粋した簡単な例です。
from multiprocessing import Process, Queue
import queue
import random
def f(q):
q.put([42, None, 'hello'])
def main():
q = Queue()
p = Process(target = f, args = (q,))
p.start()
print (q.get())
if __name__ == '__main__':
main()
出力
[42, None, 'hello']
パイプ
これは、マルチプロセスプログラムのプロセス間で通信するために使用されるデータ構造です。Pipe()関数は、デフォルトでデュプレックス(双方向)であるパイプで接続された接続オブジェクトのペアを返します。それは次のように機能します-
パイプの両端を表す接続オブジェクトのペアを返します。
すべてのオブジェクトには2つのメソッドがあります– send() そして recv()、プロセス間で通信します。
例
以下は、マルチプロセッシングの概念を理解するためにPythonの公式ドキュメントから抜粋した簡単な例です。 Pipe() マルチプロセッシングの機能。
from multiprocessing import Process, Pipe
def f(conn):
conn.send([42, None, 'hello'])
conn.close()
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p = Process(target = f, args = (child_conn,))
p.start()
print (parent_conn.recv())
p.join()
出力
[42, None, 'hello']
マネージャー
Managerは、すべてのユーザー間で共有される情報を調整する方法を提供するマルチプロセッシングモジュールのクラスです。マネージャーオブジェクトはサーバープロセスを制御します。サーバープロセスは共有オブジェクトを管理し、他のプロセスがそれらを操作できるようにします。言い換えると、マネージャーは、異なるプロセス間で共有できるデータを作成する方法を提供します。以下は、マネージャーオブジェクトのさまざまなプロパティです。
managerの主な特性は、共有オブジェクトを管理するサーバープロセスを制御することです。
もう1つの重要なプロパティは、プロセスによって共有オブジェクトが変更されたときに、すべての共有オブジェクトを更新することです。
例
以下は、マネージャーオブジェクトを使用してサーバープロセスでリストレコードを作成し、そのリストに新しいレコードを追加する例です。
import multiprocessing
def print_records(records):
for record in records:
print("Name: {0}\nScore: {1}\n".format(record[0], record[1]))
def insert_record(record, records):
records.append(record)
print("A New record is added\n")
if __name__ == '__main__':
with multiprocessing.Manager() as manager:
records = manager.list([('Computers', 1), ('Histoty', 5), ('Hindi',9)])
new_record = ('English', 3)
p1 = multiprocessing.Process(target = insert_record, args = (new_record, records))
p2 = multiprocessing.Process(target = print_records, args = (records,))
p1.start()
p1.join()
p2.start()
p2.join()
出力
A New record is added
Name: Computers
Score: 1
Name: Histoty
Score: 5
Name: Hindi
Score: 9
Name: English
Score: 3
Managerの名前空間の概念
Manager Classには、名前空間の概念が付属しています。これは、複数のプロセス間で複数の属性を共有するための迅速な方法です。名前空間には、呼び出すことができるパブリックメソッドはありませんが、書き込み可能な属性があります。
例
次のPythonスクリプトの例は、メインプロセスと子プロセス間でデータを共有するために名前空間を利用するのに役立ちます-
import multiprocessing
def Mng_NaSp(using_ns):
using_ns.x +=5
using_ns.y *= 10
if __name__ == '__main__':
manager = multiprocessing.Manager()
using_ns = manager.Namespace()
using_ns.x = 1
using_ns.y = 1
print ('before', using_ns)
p = multiprocessing.Process(target = Mng_NaSp, args = (using_ns,))
p.start()
p.join()
print ('after', using_ns)
出力
before Namespace(x = 1, y = 1)
after Namespace(x = 6, y = 10)
Ctypes-配列と値
マルチプロセッシングモジュールは、共有メモリマップにデータを格納するための配列オブジェクトと値オブジェクトを提供します。 Array 共有メモリから割り当てられたctypes配列であり、 Value 共有メモリから割り当てられたctypesオブジェクトです。
一緒にいるには、マルチプロセッシングからプロセス、値、配列をインポートします。
例
次のPythonスクリプトは、プロセス間で一部のデータを共有するためにCtypes配列と値を利用するためにPythonドキュメントから抜粋した例です。
def f(n, a):
n.value = 3.1415927
for i in range(len(a)):
a[i] = -a[i]
if __name__ == '__main__':
num = Value('d', 0.0)
arr = Array('i', range(10))
p = Process(target = f, args = (num, arr))
p.start()
p.join()
print (num.value)
print (arr[:])
出力
3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
順次プロセスの通信(CSP)
CSPは、システムと並行モデルを備えた他のシステムとの相互作用を説明するために使用されます。CSPは、メッセージパッシングを介して並行プログラムまたはプログラムを作成するためのフレームワークであるため、並行性を記述するのに効果的です。
Pythonライブラリ– PyCSP
CSPにあるコアプリミティブを実装するために、PythonにはPyCSPと呼ばれるライブラリがあります。実装を非常に短く読みやすくするため、非常に簡単に理解できます。以下は、PyCSPの基本的なプロセスネットワークです。
上記のPyCSPプロセスネットワークには、Process1とProcess 2の2つのプロセスがあります。これらのプロセスは、チャネル1とチャネル2の2つのチャネルを介してメッセージを渡すことによって通信します。
PyCSPのインストール
次のコマンドの助けを借りて、PythonライブラリPyCSPをインストールできます-
pip install PyCSP
例
次のPythonスクリプトは、2つのプロセスを互いに並行して実行するための簡単な例です。それはPyCSPpythonlibabaryの助けを借りて行われます-
from pycsp.parallel import *
import time
@process
def P1():
time.sleep(1)
print('P1 exiting')
@process
def P2():
time.sleep(1)
print('P2 exiting')
def main():
Parallel(P1(), P2())
print('Terminating')
if __name__ == '__main__':
main()
上記のスクリプトでは、2つの関数、つまり P1 そして P2 作成され、装飾されています @process それらをプロセスに変換するため。
出力
P2 exiting
P1 exiting
Terminating