กระบวนการสื่อสาร
การสื่อสารระหว่างกระบวนการหมายถึงการแลกเปลี่ยนข้อมูลระหว่างกระบวนการ จำเป็นต้องแลกเปลี่ยนข้อมูลระหว่างกระบวนการสำหรับการพัฒนาแอปพลิเคชันแบบขนาน แผนภาพต่อไปนี้แสดงกลไกการสื่อสารต่างๆสำหรับการซิงโครไนซ์ระหว่างกระบวนการย่อยต่างๆ -
กลไกการสื่อสารต่างๆ
ในส่วนนี้เราจะเรียนรู้เกี่ยวกับกลไกการสื่อสารต่างๆ กลไกต่างๆอธิบายไว้ด้านล่าง -
คิว
คิวสามารถใช้ได้กับโปรแกรมแบบหลายกระบวนการ คลาสคิวของmultiprocessing โมดูลคล้ายกับไฟล์ Queue.Queueชั้นเรียน ดังนั้นสามารถใช้ API เดียวกันได้Multiprocessing.Queue จัดเตรียมเธรดและประมวลผลกลไก FIFO (เข้าก่อนออกก่อน) ที่ปลอดภัยในการสื่อสารระหว่างกระบวนการต่างๆ
ตัวอย่าง
ต่อไปนี้เป็นตัวอย่างง่ายๆที่นำมาจากเอกสารอย่างเป็นทางการของ python เกี่ยวกับการประมวลผลหลายกระบวนการเพื่อทำความเข้าใจแนวคิดของคลาส Queue ของการประมวลผลหลายขั้นตอน
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 () ส่งคืนคู่ของวัตถุเชื่อมต่อที่เชื่อมต่อกันโดยไปป์ซึ่งโดยค่าเริ่มต้นคือ duplex (สองทาง) มันทำงานในลักษณะต่อไปนี้ -
ส่งคืนคู่ของวัตถุการเชื่อมต่อที่แสดงถึงปลายทั้งสองของท่อ
ทุกวัตถุมีสองวิธี - 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 เป็นคลาสของโมดูลการประมวลผลหลายขั้นตอนที่ให้วิธีการประสานข้อมูลที่แชร์ระหว่างผู้ใช้ทั้งหมด อ็อบเจ็กต์ตัวจัดการควบคุมกระบวนการเซิร์ฟเวอร์ซึ่งจัดการอ็อบเจ็กต์ที่แบ่งใช้และอนุญาตให้โปรเซสอื่นจัดการอ็อบเจ็กต์เหล่านั้น กล่าวอีกนัยหนึ่งผู้จัดการมีวิธีสร้างข้อมูลที่สามารถใช้ร่วมกันระหว่างกระบวนการต่างๆ ต่อไปนี้เป็นคุณสมบัติที่แตกต่างกันของวัตถุผู้จัดการ -
คุณสมบัติหลักของผู้จัดการคือการควบคุมกระบวนการเซิร์ฟเวอร์ซึ่งจัดการอ็อบเจ็กต์ที่แบ่งใช้
คุณสมบัติที่สำคัญอีกประการหนึ่งคือการอัพเดตอ็อบเจ็กต์ที่แบ่งใช้ทั้งหมดเมื่อกระบวนการใด ๆ แก้ไข
ตัวอย่าง
ต่อไปนี้เป็นตัวอย่างที่ใช้อ็อบเจ็กต์ตัวจัดการสำหรับสร้างเรกคอร์ดรายการในกระบวนการเซิร์ฟเวอร์จากนั้นเพิ่มเร็กคอร์ดใหม่ในรายการนั้น
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
แนวคิดของ Namespaces ใน Manager
คลาสผู้จัดการมาพร้อมกับแนวคิดของเนมสเปซซึ่งเป็นวิธีการที่รวดเร็วในการแบ่งปันแอตทริบิวต์ต่างๆในหลายกระบวนการ เนมสเปซไม่มีคุณลักษณะสาธารณะใด ๆ ซึ่งสามารถเรียกใช้ได้ แต่มีแอตทริบิวต์ที่เขียนได้
ตัวอย่าง
ตัวอย่างสคริปต์ 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 และ Value
Multiprocessing module จัดเตรียมอ็อบเจ็กต์ Array และ Value สำหรับจัดเก็บข้อมูลในแผนที่หน่วยความจำแบบแบ่งใช้ Array เป็นอาร์เรย์ ctypes ที่จัดสรรจากหน่วยความจำแบบแบ่งใช้และ Value เป็นวัตถุ ctypes ที่จัดสรรจากหน่วยความจำแบบแบ่งใช้
ในการใช้งานให้นำเข้ากระบวนการค่าอาร์เรย์จากการประมวลผลหลายกระบวนการ
ตัวอย่าง
สคริปต์ Python ต่อไปนี้เป็นตัวอย่างที่นำมาจากเอกสาร python เพื่อใช้ประโยชน์จาก Ctypes Array และ Value สำหรับการแบ่งปันข้อมูลระหว่างกระบวนการ
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
สำหรับการใช้งาน Core Primitives ที่พบใน CSP Python มีไลบรารีที่เรียกว่า PyCSP ช่วยให้การใช้งานสั้นและอ่านง่ายเพื่อให้สามารถเข้าใจได้ง่ายมาก ต่อไปนี้เป็นเครือข่ายกระบวนการพื้นฐานของ PyCSP -
ในเครือข่ายกระบวนการ PyCSP ข้างต้นมีสองกระบวนการ - กระบวนการ 1 และกระบวนการ 2 กระบวนการเหล่านี้สื่อสารโดยส่งข้อความผ่านสองช่องทาง - ช่องทาง 1 และช่องทาง 2
การติดตั้ง PyCSP
ด้วยความช่วยเหลือของคำสั่งต่อไปนี้เราสามารถติดตั้ง Python library PyCSP -
pip install PyCSP
ตัวอย่าง
การทำตามสคริปต์ Python เป็นตัวอย่างง่ายๆสำหรับการรันสองกระบวนการควบคู่กัน ทำได้ด้วยความช่วยเหลือของ PyCSP python libabary -
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()
ในสคริปต์ข้างต้นมีสองฟังก์ชันคือ P1 และ P2 ถูกสร้างขึ้นแล้วตกแต่งด้วย @process สำหรับการแปลงเป็นกระบวนการ
เอาต์พุต
P2 exiting
P1 exiting
Terminating