Introducción
Cuando se utiliza el módulo multiprocessing
de Python, la ejecución eficiente del código suele depender de la minimización de la sobrecarga. Optimizar su código multiprocesamiento no solo acelera sus programas, sino que también los hace más escalables y eficientes en cuanto a recursos. En este tutorial, abordaremos las mejores prácticas y técnicas para optimizar sus flujos de trabajo de multiprocesamiento mediante la reducción de la sobrecarga de la comunicación entre procesos (IPC), la gestión eficaz de los grupos de procesos y el aprovechamiento de la memoria compartida cuando sea apropiado.
Minimización de la sobrecarga de la comunicación entre procesos
La comunicación entre procesos (IPC) puede ser un importante cuello de botella para el rendimiento. A continuación se presentan algunas estrategias para reducir su impacto:
Procesamiento por lotes:
En lugar de enviar muchos mensajes pequeños entre procesos, agrupa los datos por lotes para minimizar el número de comunicaciones.Evitar la transferencia innecesaria de datos:
Pase solo la información esencial entre procesos. Utiliza memoria compartida para objetos de datos grandes si es posible.Estructuras de datos eficientes:
Utilice estructuras de datos ligeras que sean más rápidas de serializar y transmitir.
Ejemplo: procesamiento por lotes con Pool.map
import multiprocessing
import time
def process_data(data_batch):
# Simula el procesamiento de un lote de datos
1)
time.sleep(return sum(data_batch)
if __name__ == "__main__":
= list(range(1, 101))
data # Agrupar los datos en lotes de 10
= [data[i:i+10] for i in range(0, len(data), 10)]
batches
with multiprocessing.Pool(processes=4) as pool:
= pool.map(process_data, batches)
results
print("Processed Results:", results)
Gestión eficaz de grupos de procesos
El uso adecuado de los grupos de procesos puede ayudarle a lograr un buen equilibrio entre el paralelismo y la utilización de los recursos.
Ajustar el número de procesos:
Experimente con el número de procesos de trabajo para encontrar el equilibrio óptimo para su carga de trabajo específica.Uso de gestores de contexto:
Utilice el patrónwith multiprocessing.Pool() as pool:
para garantizar que los procesos se cierran correctamente después de la ejecución.Mapeo asíncrono:
Para cargas de trabajo más dinámicas, considere la posibilidad de utilizarapply_async
oimap
para gestionar las tareas de forma asíncrona.
Ejemplo: uso de apply_async con una devolución de llamada
import multiprocessing
def compute_square(n):
return n * n
def collect_result(result):
results.append(result)
if __name__ == "__main__":
= [1, 2, 3, 4, 5]
numbers = []
results
with multiprocessing.Pool(processes=3) as pool:
for number in numbers:
=(number,), callback=collect_result)
pool.apply_async(compute_square, args
pool.close()
pool.join()
print("Squares:", results)
Uso de memoria compartida
En escenarios en los que varios procesos necesitan acceder a los mismos datos sin copiarlos, los objetos de memoria compartida pueden reducir significativamente la sobrecarga.
Matrices y valores compartidos:
Utilicemultiprocessing.Array
ymultiprocessing.Value
para compartir datos entre procesos sin la sobrecarga de la serialización.Vistas de memoria:
Aproveche las vistas de memoria o el módulomultiprocessing.shared_memory
(disponible en Python 3.8+) para trabajar con bloques de memoria compartida.
Ejemplo: uso de una matriz compartida
import multiprocessing
import numpy as np
def increment_array(shared_array, size):
# Convertir la memoria compartida en una matriz numpy
= np.frombuffer(shared_array.get_obj())
arr for i in range(size):
+= 1
arr[i]
if __name__ == "__main__":
= 10
size # Crear una matriz compartida de números enteros
= multiprocessing.Array('i', range(size))
shared_array
= []
processes for _ in range(4): # Crear 4 procesos
= multiprocessing.Process(target=increment_array, args=(shared_array, size))
p
processes.append(p)
p.start()
for p in processes:
p.join()
# Convierte la memoria compartida en una matriz numpy para mostrar el resultado
= np.frombuffer(shared_array.get_obj())
result_array print("Resulting Array:", result_array)
Conclusión
La optimización del código de multiprocesamiento en Python implica una combinación de estrategias destinadas a reducir la sobrecarga y maximizar la eficiencia de la ejecución simultánea. Al minimizar la comunicación entre procesos, gestionar eficazmente los grupos de procesos y utilizar la memoria compartida cuando sea apropiado, puede mejorar significativamente el rendimiento de sus aplicaciones. Experimente con estas técnicas para determinar cuál funciona mejor para sus casos de uso específicos.
Lecturas adicionales
- Multiprocesamiento frente a multihilos en Python
- Procesamiento paralelo en Python: acelere su código
- Depuración y registro eficaces en Python: mejores prácticas
Feliz programación, y que tus aplicaciones Python se ejecuten más rápido y de forma más eficiente!
Explorar más artículos
Aquí hay más artículos de la misma categoría para ayudarte a profundizar en el tema.
Reutilización
Cómo citar
@online{kassambara2024,
author = {Kassambara, Alboukadel},
title = {Optimización del código de multiprocesamiento en Python},
date = {2024-02-05},
url = {https://www.datanovia.com/es/learn/programming/python/advanced/parallel-processing/optimizing-multiprocessing-code.html},
langid = {es}
}