- 1 1. Edición básica: ¿Qué es el multiprocesamiento en Python?
- 2 2. Edición práctica: Cómo usar el módulo multiprocessing
- 3 3. Sección avanzada: Manejo de errores y optimización de rendimiento
- 3.1 3.1 Errores comunes en multiprocessing y sus contramedidas
- 3.2 3.2 Técnicas de optimización de rendimiento
- 3.3 3.3 Resumen
- 4 4. FAQ: Dudas comunes y soluciones
- 4.1 4.1 Multiprocesamiento y multihilo en Python, ¿cuál usar?
- 4.2 4.2 ¿Por qué multiprocessing se siente «lento»?
- 4.3 4.3 ¿Cómo compartir diccionarios o listas en multiprocesamiento?
- 4.4 4.4 ¿Cuáles son los errores comunes en multiprocessing.Pool y cómo manejarlos?
- 4.5 4.5 ¿Cómo depurar multiprocesamiento en Python?
- 5 5. Resumen y recursos de aprendizaje adicionales
- 6 5.4 En conclusión
1. Edición básica: ¿Qué es el multiprocesamiento en Python?
1.1 ¿Qué es el multiprocesamiento?
El multiprocesamiento es una técnica para ejecutar simultáneamente múltiples procesos (unidades de ejecución independientes). En Python, se puede implementar fácilmente el multiprocesamiento utilizando el módulo multiprocessing
.
Características del multiprocesamiento
- Cada proceso tiene un espacio de memoria independiente
- Puede aprovechar al máximo los núcleos de CPU
- Es necesario la comunicación entre procesos (usando
Queue
oPipe
)
Escenarios de uso específicos
- Procesos que involucran grandes cantidades de cálculos (aprendizaje automático, simulación numérica)
- Tareas que aprovechan completamente la CPU (procesamiento de imágenes, análisis de datos)
1.2 Diferencias con el multihilo
En Python también hay un mecanismo de procesamiento paralelo llamado «multihilo». ¿En qué se diferencian el multiprocesamiento y el multihilo?
Ítem | Multiprocesamiento | Multihilo |
---|---|---|
Compartir memoria | No (procesos independientes) | Sí (dentro del mismo proceso) |
Impacto de GIL | No afectado | Afectado |
Orientado a CPU | ◎ | ✕ |
Orientado a E/S | △ | ◎ |
Intercambio de datos | Queue o Pipe son necesarios | Se puede usar memoria compartida |
¿Qué es GIL (Global Interpreter Lock)?
El intérprete estándar de Python (CPython) tiene un mecanismo llamado «GIL», por lo que incluso usando multihilo, solo se puede ejecutar un hilo a la vez. Por esta razón, si se desea aprovechar completamente la CPU, el multiprocesamiento es adecuado.
1.3 Ejemplo simple de implementación de multiprocesamiento en Python
import multiprocessing
import time
def worker(n):
print(f"Proceso {n} iniciado")
time.sleep(2)
print(f"Proceso {n} finalizado")
if __name__ == "__main__":
process_list = []
# Crear 3 procesos
for i in range(3):
p = multiprocessing.Process(target=worker, args=(i,))
process_list.append(p)
p.start()
# Esperar a que todos los procesos terminen
for p in process_list:
p.join()
print("Todos los procesos finalizados")
1.4 Puntos de atención al usar multiprocesamiento
1. En Windows, if __name__ == "__main__":
es obligatorio
En el entorno de Windows, al usar multiprocessing.Process()
, si no se escribe if __name__ == "__main__":
, se produce un error.
Código incorrecto (produce error)
import multiprocessing
def worker():
print("Hello from process")
p = multiprocessing.Process(target=worker)
p.start()
Este código produce un error en Windows.
Código correcto
import multiprocessing
def worker():
print("Hello from process")
if __name__ == "__main__":
p = multiprocessing.Process(target=worker)
p.start()
p.join()
Al agregar if __name__ == "__main__":
, funciona correctamente también en Windows.
1.5 Resumen
- ¿Qué es el multiprocesamiento? → Método para ejecutar múltiples procesos en paralelo
- Diferencias con el multihilo → No afectado por GIL, adecuado para tareas orientadas a CPU
- Ejemplo simple de implementación en Python → Usar
multiprocessing.Process()
- Puntos de atención en Windows → Se necesita
if __name__ == "__main__":
2. Edición práctica: Cómo usar el módulo multiprocessing
2.1 Resumen del módulo multiprocessing
multiprocessing
El módulo es una biblioteca estándar para realizar procesamiento paralelo basado en procesos en Python.
Al usar este módulo, se puede aprovechar al máximo los núcleos de CPU y evitar las restricciones del GIL.
Funciones principales de multiprocessing
Funcionalidad | Descripción |
---|---|
Process | Crear y ejecutar procesos individuales |
Queue | Enviar y recibir datos entre procesos |
Pipe | Intercambiar datos entre dos procesos |
Value & Array | Utilizar memoria compartida entre procesos |
Pool | Crear un grupo de procesos y realizar procesamiento paralelo de manera eficiente |
2.2 Process
Uso básico de la clase
Para crear un nuevo proceso en Python, se utiliza la clase multiprocessing.Process
.
Creación básica de procesos
import multiprocessing
import time
def worker(n):
print(f"Proceso {n} iniciado")
time.sleep(2)
print(f"Proceso {n} finalizado")
if __name__ == "__main__":
p1 = multiprocessing.Process(target=worker, args=(1,))
p2 = multiprocessing.Process(target=worker, args=(2,))
p1.start()
p2.start()
p1.join()
p2.join()
print("Todos los procesos finalizados")
2.3 Comunicación entre procesos (Queue & Pipe)
Envío y recepción de datos con Queue
import multiprocessing
def worker(q):
q.put("Hola desde el proceso hijo")
if __name__ == "__main__":
q = multiprocessing.Queue()
p = multiprocessing.Process(target=worker, args=(q,))
p.start()
p.join()
# Obtener datos del proceso hijo
print(q.get())
2.4 Memoria compartida con Value
y Array
import multiprocessing
def worker(val, arr):
val.value = 3.14 # Cambiar el valor de la memoria compartida
arr[0] = 42 # Cambiar el valor del arreglo
if __name__ == "__main__":
val = multiprocessing.Value('d', 0.0) # 'd' es tipo double
arr = multiprocessing.Array('i', [0, 1, 2]) # 'i' es tipo entero
p = multiprocessing.Process(target=worker, args=(val, arr))
p.start()
p.join()
print(f"val: {val.value}, arr: {arr[:]}")
2.5 Gestión de procesos con la clase Pool
Procesamiento paralelo con Pool
import multiprocessing
def square(n):
return n * n
if __name__ == "__main__":
with multiprocessing.Pool(4) as pool:
results = pool.map(square, range(10))
print(results)
2.6 Resumen
- Con el módulo
multiprocessing
, se puede implementar procesamiento paralelo de manera sencilla - Crear procesos individuales con la clase
Process
- Con
Queue
oPipe
, es posible compartir datos entre procesos - Compartir memoria con
Value
oArray
- Con la clase
Pool
, se puede procesar grandes cantidades de datos de manera eficiente

3. Sección avanzada: Manejo de errores y optimización de rendimiento
3.1 Errores comunes en multiprocessing y sus contramedidas
Error 1: Error por ausencia de if __name__ == "__main__":
en el entorno de Windows
Mensaje de error
RuntimeError: freeze_support() must be called if program is run in frozen mode
Solución
import multiprocessing
def worker():
print("Hello from process")
if __name__ == "__main__": # Esto es necesario
p = multiprocessing.Process(target=worker)
p.start()
p.join()
Error 2: PicklingError (no se puede pasar una función entre procesos)
Mensaje de error
AttributeError: Can't pickle local object 'main..'
Solución
import multiprocessing
def square(x): # Hacerlo una función global
return x * x
if __name__ == "__main__":
with multiprocessing.Pool(4) as pool:
results = pool.map(square, range(10)) # Evitar lambda
print(results)
Error 3: Deadlock (el proceso se detiene indefinidamente)
Solución
import multiprocessing
def worker(q):
q.put("data")
if __name__ == "__main__":
q = multiprocessing.Queue()
p = multiprocessing.Process(target=worker, args=(q,))
p.start()
print(q.get()) # Recibir los datos
p.join() # Aquí termina normalmente
3.2 Técnicas de optimización de rendimiento
Optimización 1: Configurar el número de procesos de manera adecuada
import multiprocessing
def worker(n):
return n * n
if __name__ == "__main__":
num_workers = multiprocessing.cpu_count() # Obtener el número de núcleos de CPU
with multiprocessing.Pool(num_workers) as pool:
results = pool.map(worker, range(100))
print(results)
Optimización 2: Usar Pool.starmap()
import multiprocessing
def multiply(a, b):
return a * b
if __name__ == "__main__":
with multiprocessing.Pool(4) as pool:
results = pool.starmap(multiply, [(1, 2), (3, 4), (5, 6)])
print(results)
Optimización 3: Aprovechar la memoria compartida
import multiprocessing
import ctypes
def worker(shared_array):
shared_array[0] = 99 # Cambiar el valor de la memoria compartida
if __name__ == "__main__":
shared_array = multiprocessing.Array(ctypes.c_int, [1, 2, 3]) # Crear memoria compartida
p = multiprocessing.Process(target=worker, args=(shared_array,))
p.start()
p.join()
print(shared_array[:]) # [99, 2, 3]
3.3 Resumen
- Explicación de los métodos para evitar errores que ocurren fácilmente en
multiprocessing
- Puntos de optimización de rendimiento:
- Configurar el número de procesos de manera adecuada
- Aprovechar starmap()
- Acelerar con memoria compartida
4. FAQ: Dudas comunes y soluciones
4.1 Multiprocesamiento y multihilo en Python, ¿cuál usar?
Respuesta
- CPU-bound (procesos con alta carga computacional) → Multiprocesamiento (multiprocessing)
- I/O-bound (procesos de archivo y red) → Multihilo (threading)
Tipo de proceso | Procesamiento paralelo adecuado |
---|---|
CPU-bound (cálculo numérico, procesamiento de imágenes, etc.) | Multiprocesamiento (multiprocessing) |
I/O-bound (solicitudes de archivo y API, etc.) | Multihilo (threading) |
4.2 ¿Por qué multiprocessing
se siente «lento»?
Respuesta
- El costo de creación de procesos es alto → Usa
Pool
- Hay demasiadas copias de datos → Usa memoria compartida (
Value
,Array
) - Procesamiento de muchas tareas pequeñas → Prueba
concurrent.futures.ThreadPoolExecutor
import multiprocessing
def worker(n):
return n * n
if __name__ == "__main__":
with multiprocessing.Pool(multiprocessing.cpu_count()) as pool:
results = pool.map(worker, range(100))
print(results)
4.3 ¿Cómo compartir diccionarios o listas en multiprocesamiento?
Respuesta
Usa multiprocessing.Manager()
import multiprocessing
def worker(shared_list):
shared_list.append(100) # Actualiza la lista compartida
if __name__ == "__main__":
with multiprocessing.Manager() as manager:
shared_list = manager.list([1, 2, 3])
p = multiprocessing.Process(target=worker, args=(shared_list,))
p.start()
p.join()
print(shared_list) # [1, 2, 3, 100]
4.4 ¿Cuáles son los errores comunes en multiprocessing.Pool
y cómo manejarlos?
Error | Causa | Solución |
---|---|---|
AttributeError: Can't pickle local object | Se está pasando una lambda o función local | Usa una función global |
RuntimeError: freeze_support() must be called | En entornos Windows, falta if __name__ == "__main__": __ | Agrega if __name__ == "__main__": |
EOFError: Ran out of input | Los procesos en Pool no terminaron correctamente | Llama adecuadamente a pool.close() y pool.join() |
4.5 ¿Cómo depurar multiprocesamiento en Python?
Respuesta
Usa multiprocessing.log_to_stderr()
import multiprocessing
import logging
def worker(n):
logger = multiprocessing.get_logger()
logger.info(f"Proceso {n} en ejecución")
if __name__ == "__main__":
multiprocessing.log_to_stderr(logging.INFO) # Habilita los logs
p = multiprocessing.Process(target=worker, args=(1,))
p.start()
p.join()
5. Resumen y recursos de aprendizaje adicionales
5.1 Resumen de este artículo
Conceptos básicos del multiprocesamiento
- ¿Qué es el multiprocesamiento? → Tecnología que ejecuta múltiples procesos en paralelo para maximizar el uso de la CPU
- Diferencia con el multihilo
- Multiprocesamiento → Adecuado para procesamiento CPU-bound (cálculos numéricos, procesamiento de imágenes, etc.)
- Multihilo → Adecuado para procesamiento I/O-bound (procesamiento de archivos, comunicación de red, etc.)
multiprocessing
Uso del módulo
- Usando la clase
Process
para crear procesos individuales - Usando
Queue
oPipe
para enviar y recibir datos entre procesos - Aprovechando
Value
oArray
para utilizar memoria compartida - Usando la clase
Pool
para ejecutar procesamiento paralelo de manera eficiente
Manejo de errores y optimización de rendimiento
- Errores comunes
- Si no se escribe
if __name__ == "__main__":
, se produce un error en Windows - Las funciones
lambda
o locales provocan PicklingError - Olvidar
Queue.get()
causa deadlock - Optimización de rendimiento
- Aprovechar
Pool
para reducir el costo de creación de procesos - Usar
starmap()
para pasar múltiples argumentos - Utilizar
multiprocessing.shared_memory
para reducir la sobrecarga de copia de datos
5.2 Recursos de aprendizaje adicionales
1. Documentación oficial de Python
2. Tutoriales en línea
5.3 Hacia el uso futuro
Al utilizar adecuadamente multiprocessing
de Python, se puede usar la CPU de manera eficiente y crear programas de alto rendimiento.
Tecnologías que aprender a continuación
- Procesamiento asíncrono (asyncio) → Paralelizar procesamiento I/O-bound
- concurrent.futures → Gestión integrada de hilos y procesos
5.4 En conclusión
En este artículo, explicamos en detalle «Multiprocesamiento en Python» desde los fundamentos hasta la práctica y la aplicación.
Aplique el conocimiento aprendido en este artículo a proyectos reales. ¡Pruébelo! 🚀