Logo de fravelz

Notas de Hacking

Fravelz

Multiprocessing en Python


¿Qué es multiprocessing? {#qué-es-multiprocessing}

multiprocessing permite ejecutar varios procesos en paralelo, aprovechando todos los núcleos del CPU. A diferencia de los hilos (threading), cada proceso tiene su propia memoria → no hay bloqueo por el GIL (Global Interpreter Lock).

Es ideal para tareas pesadas en CPU, como cálculos, IA, simulaciones, etc.


Conceptos básicos {#conceptos-básicos}

Crear un proceso {#crear-un-proceso}

from multiprocessing import Process

def tarea():
print("Ejecutando en otro proceso")

if __name__ == "__main__":
p = Process(target=tarea)  # Crear proceso
p.start()                  # Iniciar
p.join()                   # Esperar a que termine
print("Proceso finalizado")
  • target: función a ejecutar.
  • args: argumentos para esa función.
  • start(): inicia el proceso.
  • join(): bloquea hasta que el proceso termina.

Enviar datos entre procesos {#enviar-datos-entre-procesos}

Con Queue {#con-queue}

from multiprocessing import Process, Queue

def productor(q):
for i in range(3):
q.put(i)  # Enviar a la cola

def consumidor(q):
while not q.empty():
print("Recibido:", q.get())

if __name__ == "__main__":
q = Queue()
p1 = Process(target=productor, args=(q,))
p2 = Process(target=consumidor, args=(q,))
p1.start(); p1.join()
p2.start(); p2.join()

Con Pipe {#con-pipe}

from multiprocessing import Process, Pipe

def enviar(conexion):
conexion.send("Hola desde otro proceso")
conexion.close()

if __name__ == "__main__":
conn1, conn2 = Pipe()
p = Process(target=enviar, args=(conn2,))
p.start()
print(conn1.recv())  # Recibe mensaje
p.join()

Uso de Pool (grupo de procesos) {#uso-de-pool-grupo-de-procesos}

Permite ejecutar una función muchas veces en paralelo fácilmente.

from multiprocessing import Pool

def cuadrado(x):
return x * x

if __name__ == "__main__":
with Pool(4) as pool:  # 4 procesos
resultados = pool.map(cuadrado, [1, 2, 3, 4, 5])
print(resultados)

➡️ Ejecuta cuadrado en paralelo para cada valor.


Variables compartidas {#variables-compartidas}

Para compartir datos entre procesos de forma segura:

Value y Array {#value-y-array}

from multiprocessing import Process, Value, Array

def modificar(v, a):
v.value += 10
for i in range(len(a)):
a[i] *= 2

if __name__ == "__main__":
v = Value('i', 5)           # Entero compartido
a = Array('i', [1, 2, 3])   # Arreglo compartido
p = Process(target=modificar, args=(v, a))
p.start(); p.join()
print(v.value, a[:])

Sincronización entre procesos {#sincronización-entre-procesos}

Se usan mecanismos como Lock, Event, Semaphore, etc., para evitar conflictos.

Ejemplo con Lock {#ejemplo-con-lock}

from multiprocessing import Process, Lock

def imprimir(lock, texto):
with lock:
print(texto)

if __name__ == "__main__":
lock = Lock()
for i in range(3):
Process(target=imprimir, args=(lock, f"Proceso {i}")).start()

Ejemplo completo {#ejemplo-completo}

from multiprocessing import Process, Queue, current_process

def trabajo(q):
nombre = current_process().name
q.put(f"{nombre} inicia tarea")
time.sleep(1)
q.put(f"{nombre} termina tarea")

if __name__ == "__main__":
q = Queue()
procesos = [Process(target=trabajo, args=(q,)) for _ in range(4)]

for p in procesos: p.start()
for p in procesos: p.join()

while not q.empty():
print(q.get())

Resumen rápido {#resumen-rápido}