Compartir grandes volúmenes de datos entre procesos vía colas o pipes puede ser lento por la serialización (pickle) y la copia. La memoria compartida permite que varios procesos accedan al mismo buffer sin copiarlo, ahorrando tiempo y RAM.
Ganas velocidad, pero también asumes la responsabilidad de sincronizar accesos y liberar el segmento.
shared_memory en multiprocessing (Python 3.8+)name) o se adjunta a uno existente.SharedMemory(create=True, size=...) para crear; SharedMemory(name=...) para adjuntar; close() cierra el handle; unlink() libera el segmento.unlink() deja el segmento huérfano.memoryview o se convierten en arrays de numpy o array para acceso cómodo.'i' para enteros, 'd' para doubles).lock (por defecto True) para proteger escrituras.multiprocessing.Lock o división estricta de rangos.close() y unlink() en un bloque de limpieza.Este programa crea un arreglo grande en memoria compartida, reparte su procesamiento entre procesos y combina el resultado sin copiar datos.
La clave es dividir el buffer en tramos disjuntos para que cada proceso trabaje sin bloquear.
import math
import multiprocessing as mp
from multiprocessing import shared_memory
import time
def inicializar(shm_name, length):
shm = shared_memory.SharedMemory(name=shm_name)
buf = memoryview(shm.buf).cast("I") # unsigned int
for i in range(length):
buf[i] = i
buf.release()
shm.close()
def procesar_parte(shm_name, start, end):
shm = shared_memory.SharedMemory(name=shm_name)
buf = memoryview(shm.buf).cast("I")
for i in range(start, end):
buf[i] = buf[i] * 2 + (1 if buf[i] % 2 == 0 else 0)
buf.release()
shm.close()
def verificar(shm_name, length):
shm = shared_memory.SharedMemory(name=shm_name)
buf = memoryview(shm.buf).cast("I")
ok = all(buf[i] == i * 2 + (1 if i % 2 == 0 else 0) for i in range(length))
buf.release()
shm.close()
return ok
def main():
length = 500_000
size_bytes = length * 4 # uint32
shm = shared_memory.SharedMemory(create=True, size=size_bytes)
shm_name = shm.name
# Inicializa datos en el segmento
inicializar(shm_name, length)
workers = mp.cpu_count()
chunk = math.ceil(length / workers)
procesos = []
inicio = time.perf_counter()
for idx in range(workers):
start = idx * chunk
end = min(start + chunk, length)
if start >= end:
continue
p = mp.Process(target=procesar_parte, args=(shm_name, start, end))
p.start()
procesos.append(p)
for p in procesos:
p.join()
duracion = time.perf_counter() - inicio
ok = verificar(shm_name, length)
print(f"Procesado en {duracion:.2f}s con {len(procesos)} procesos. Verificación: {ok}")
shm.close()
shm.unlink() # libera el segmento
if __name__ == "__main__":
mp.freeze_support() # seguro en Windows
main()
El ejemplo evita copiar datos grandes: todos los procesos leen y escriben sobre el mismo buffer. Aun así, es necesario dividir rangos para no pisar memoria y limpiar con close() y unlink() para liberar el segmento compartido.