Intercomunicação de Processos

Intercomunicação de processos significa a troca de dados entre processos. É necessário trocar os dados entre os processos para o desenvolvimento da aplicação paralela. O diagrama a seguir mostra os vários mecanismos de comunicação para sincronização entre vários subprocessos -

Vários mecanismos de comunicação

Nesta seção, aprenderemos sobre os vários mecanismos de comunicação. Os mecanismos são descritos abaixo -

Filas

As filas podem ser usadas com programas multiprocessos. A classe Queue demultiprocessing módulo é semelhante ao Queue.Queueclasse. Portanto, a mesma API pode ser usada.Multiprocessing.Queue nos fornece um mecanismo de comunicação entre processos FIFO (first-in first-out) seguro para processos e threads.

Exemplo

A seguir está um exemplo simples retirado da documentação oficial do python sobre multiprocessamento para entender o conceito da classe Queue de multiprocessamento.

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()

Resultado

[42, None, 'hello']

Tubos

É uma estrutura de dados usada para a comunicação entre processos em programas multiprocessos. A função Pipe () retorna um par de objetos de conexão conectados por um pipe que por padrão é duplex (bidirecional). Funciona da seguinte maneira -

  • Ele retorna um par de objetos de conexão que representam as duas extremidades do tubo.

  • Cada objeto tem dois métodos - send() e recv(), para se comunicar entre processos.

Exemplo

A seguir está um exemplo simples tirado da documentação oficial do python sobre multiprocessamento para entender o conceito de Pipe() função de multiprocessamento.

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()

Resultado

[42, None, 'hello']

Gerente

Manager é uma classe de módulo de multiprocessamento que fornece uma maneira de coordenar informações compartilhadas entre todos os seus usuários. Um objeto gerenciador controla um processo de servidor, que gerencia objetos compartilhados e permite que outros processos os manipulem. Em outras palavras, os gerentes fornecem uma maneira de criar dados que podem ser compartilhados entre diferentes processos. A seguir estão as diferentes propriedades do objeto gerente -

  • A principal propriedade do gerenciador é controlar um processo do servidor, que gerencia os objetos compartilhados.

  • Outra propriedade importante é atualizar todos os objetos compartilhados quando algum processo os modifica.

Exemplo

A seguir está um exemplo que usa o objeto gerenciador para criar um registro de lista no processo do servidor e, em seguida, adicionar um novo registro nessa lista.

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()

Resultado

A New record is added

Name: Computers
Score: 1

Name: Histoty
Score: 5

Name: Hindi
Score: 9

Name: English
Score: 3

Conceito de namespaces no Manager

O Manager Class vem com o conceito de namespaces, que é um método de maneira rápida para compartilhar vários atributos em vários processos. Os namespaces não apresentam nenhum método público, que pode ser chamado, mas têm atributos graváveis.

Exemplo

O exemplo de script Python a seguir nos ajuda a utilizar namespaces para compartilhar dados entre o processo principal e o processo filho -

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)

Resultado

before Namespace(x = 1, y = 1)
after Namespace(x = 6, y = 10)

Ctypes-Array and Value

O módulo de multiprocessamento fornece objetos Array e Value para armazenar os dados em um mapa de memória compartilhada. Array é uma matriz ctypes alocada da memória compartilhada e Value é um objeto ctypes alocado da memória compartilhada.

Para estar com, importe Process, Value, Array do multiprocessamento.

Exemplo

Seguindo o script Python, está um exemplo retirado da documentação do python para utilizar Ctypes Array and Value para compartilhar alguns dados entre processos.

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[:])

Resultado

3.1415927
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

Processos de comunicação sequencial (CSP)

CSP é usado para ilustrar a interação de sistemas com outros sistemas apresentando modelos concorrentes. CSP é uma estrutura para escrever concorrentes ou programas por meio de passagem de mensagens e, portanto, é eficaz para descrever a simultaneidade.

Biblioteca Python - PyCSP

Para implementar os primitivos básicos encontrados no CSP, o Python tem uma biblioteca chamada PyCSP. Ele mantém a implementação muito curta e legível para que possa ser entendida facilmente. A seguir está a rede de processos básicos do PyCSP -

Na rede de processos PyCSP acima, há dois processos - Processo 1 e Processo 2. Esses processos se comunicam passando mensagens por meio de dois canais - canal 1 e canal 2.

Instalando PyCSP

Com a ajuda do seguinte comando, podemos instalar a biblioteca Python PyCSP -

pip install PyCSP

Exemplo

Seguir o script Python é um exemplo simples para executar dois processos em paralelo um ao outro. Isso é feito com a ajuda da libabary PyCSP python -

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()

No script acima, duas funções são P1 e P2 foram criados e então decorados com @process para convertê-los em processos.

Resultado

P2 exiting
P1 exiting
Terminating