Python multiprocessing: ejecución de procesos en paralelo
Python multiprocessing te permite dividir la carga de trabajo en varios procesos y reducir así el tiempo total de ejecución. Esto supone una gran ventaja, especialmente cuando deben realizarse muchos cálculos o cuando hay grandes conjuntos de datos.
¿Qué es Python multiprocessing?
El multiprocesamiento en Python se refiere a la capacidad de ejecutar varios procesos a la vez para aprovechar al máximo el rendimiento de los sistemas de núcleo múltiple. A diferencia de los sistemas de un solo hilo, en los que las tareas se ejecutan de forma secuencial, el multiprocesamiento permite que diferentes partes del programa se ejecuten en paralelo e independientemente. Cada proceso tiene su propio espacio de memoria y se puede procesar en núcleos de procesador separados, lo que reduce significativamente el tiempo de ejecución para operaciones que requieren muchos cálculos o tienen requisitos de tiempo estrictos.
El Python multiprocessing puede utilizarse en el procesamiento y análisis de datos, por ejemplo, para procesar grandes conjuntos de datos de manera más rápida. También puede emplearse en simulaciones y cálculos de modelado, como en aplicaciones científicas, para reducir los tiempos de ejecución de cálculos complejos. Además, el multiprocesamiento se utiliza en el ámbito del web scraping para recopilar datos de varias páginas web simultáneamente, así como en el procesamiento de imágenes y visión por computadora para mejorar la eficiencia de las operaciones de análisis.
¿Dónde se puede implementar el multiprocesamiento en Python?
Python ofrece varias posibilidades de implementar el multiprocesamiento. A continuación, te presentamos tres herramientas habituales: el módulo multiprocessing
, la biblioteca concurrent.futures
y el paquete joblib
.
El módulo multiprocessing
Multiprocessing
es el módulo estándar para el multiprocesamiento de Python. Con él es posible crear procesos, intercambiar datos entre esos procesos y realizar sincronizaciones mediante bloqueos, colas y otros mecanismos.
import multiprocessing
def task(n):
result = n * n
print(f"Result: {result}")
if __name__ == "__main__":
processes = []
for i in range(1, 6):
process = multiprocessing.Process(target=task, args=(i,))
processes.append(process)
process.start()
for process in processes:
process.join()
pythonEn el anterior ejemplo se ha utilizado la clase multiprocessing.Process
para crear e iniciar procesos que ejecutan la función task()
. Esta función toma el número transferido y lo eleva al cuadrado. Después, se inicia cada proceso y se espera a que terminen antes de continuar con el programa principal. El resultado se obtiene con un f-string, que es un método de Python string format para enlazar expresiones. La secuencia de salida de los resultados no sigue un orden específico y puede variar en cada ejecución.
También puedes crear un pool de procesos con Python multiprocessing
de la siguiente manera:
import multiprocessing
def task(n):
return n * n
if __name__ == "__main__":
with multiprocessing.Pool() as pool:
results = pool.map(task, range(1, 6))
print(results) # Output: [1, 4, 9, 16, 25]
pythonCon pool.map()
se aplica la función task()
a una secuencia de datos, y se recopilan y devuelven los resultados.
La biblioteca concurrent.futures
El módulo concurrent.futures
proporciona una interfaz de alto nivel para la ejecución asíncrona y el procesamiento en paralelo de tareas. Utiliza el Pool Executor para ejecutar tareas en un pool de procesos o hilos. Este módulo ofrece una manera más sencilla de manejar tareas asíncronas y, en muchos casos, es más fácil de usar que el módulo multiprocessing de Python.
import concurrent.futures
def task(n):
return n * n
with concurrent.futures.ProcessPoolExecutor() as executor:
futures = [executor.submit(task, i) for i in range(1, 6)]
for future in concurrent.futures.as_completed(futures):
print(future.result()) # result in random order
pythonEl código utiliza el módulo concurrent.futures
para procesar tareas en paralelo con el ProcessPoolExecutor
. La función task(n)
se transfiere para números del 1 al 5. El método as_completed()
espera a que se completen las tareas y devuelve los resultados en un orden aleatorio.
joblib
joblib
es una biblioteca externa de Python diseñada para simplificar el procesamiento en paralelo, por ejemplo, para tareas repetitivas como ejecutar funciones con diferentes parámetros de entrada o trabajar con grandes cantidades de datos. Las principales funciones de joblib
son paralelizar tareas, almacenar en caché los resultados de las funciones y optimizar los recursos de memoria y computación.
from joblib import Parallel, delayed
def task(n):
return n * n
results = Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11))
print(results) # Output: Results of the function for numbers from 1 to 10
pythonCon la expresión Parallel(n_jobs=4)(delayed(task)(i) for i in range(1, 11))
se inicia la ejecución en paralelo de la función task()
para los números del 1 al 10. Parallel
está configurado con el argumento n_jobs=4
, lo que indica que se pueden procesar hasta cuatro trabajos en paralelo. Al llamar a delayed(task)(i)
, se crea la tarea que debe ejecutarse en paralelo para cada número i en el rango del 1 al 10. Es decir, se llama a la función task()
simultáneamente para cada uno de esos números. El resultado para los números del 1 al 10 se almacena en results
y se imprime.