1. Usando `multiprocesamiento`: Este es generalmente el mejor enfoque para las tareas unidas a la CPU (tareas que pasan la mayor parte de su tiempo haciendo cálculos). Crea múltiples procesos, cada uno con una parte del bucle.
`` `Python
importar multiprocesamiento
Def process_item (elemento):
"" "La función que se aplicará a cada elemento en el bucle". ""
# Su código para procesar un solo elemento va aquí
resultado =elemento * 2 # Ejemplo:duplique el elemento
Resultado de retorno
Si __name__ =='__main__':# importante para la compatibilidad de Windows
elementos =lista (rango (1000)) # Lista de ejemplo de elementos
con multiprocesamiento.pool (procesos =multiprocessing.cpu_count ()) como grupo:
Resultados =Pool.map (Process_item, elementos)
Imprimir (resultados)
`` `` ``
* `multiprocesamiento.pool`: Crea un grupo de procesos de trabajadores. `multiprocesamiento.cpu_count ()` determina el número óptimo de procesos basados en los núcleos de su sistema. Puede ajustar este número si es necesario.
* `Pool.map`: Aplica la función `Process_Item` a cada elemento en el` ítems 'ITerable. Maneja distribuir el trabajo y recopilar los resultados de manera eficiente.
* `if __name__ =='__main __':`: Esto es crucial, especialmente en las ventanas, para evitar la creación de múltiples procesos de manera recursiva.
2. Usando `concurrent.futures`: Proporciona una interfaz de nivel superior para multiprocesar y roscarse, ofreciendo más flexibilidad.
`` `Python
importación concurrente.
Def process_item (elemento):
"" "La función que se aplicará a cada elemento en el bucle". ""
# Su código para procesar un solo elemento va aquí
resultado =elemento * 2 # Ejemplo:duplique el elemento
Resultado de retorno
Si __name__ =='__main__':
elementos =lista (rango (1000))
con concurrent.futures.processpoolexecutor () como ejecutor:
resultados =list (ejecutor.map (process_item, elementos))
Imprimir (resultados)
`` `` ``
Esto es muy similar al 'multiprocesamiento', pero a menudo se considera más pitónico y más fácil de usar. `ProcessPoolExecutor` utiliza procesos, mientras que` ThreadpoolExeCutor` usa hilos (mejor para tareas de E/S).
3. Usando `Threading` (para tareas de I/O): Si su bucle implica mucha espera (por ejemplo, solicitudes de red, E/S de archivos), los subprocesos pueden ser más eficientes que los procesos. Sin embargo, el bloqueo de intérprete global (GIL) en CPython limita el verdadero paralelismo para las tareas unidas a la CPU dentro de los hilos.
`` `Python
Importación de hilo
Def process_item (elemento, resultados):
"" "La función que se aplicará a cada elemento en el bucle". ""
# Su código para procesar un solo elemento va aquí
resultado =elemento * 2 # Ejemplo:duplique el elemento
Results.append (resultado)
Si __name__ =='__main__':
elementos =lista (rango (1000))
Resultados =[]
Hilos =[]
Para el artículo en los artículos:
Thread =Threading.Thread (Target =Process_item, args =(item, resultados))
Threads.append (hilo)
Thread.Start ()
Para hilo en hilos:
Thread.Join ()
Imprimir (resultados)
`` `` ``
Este ejemplo es más complejo porque necesita administrar hilos y una lista de resultados compartido explícitamente. `concurrente.futures.threadpoolexecutor` simplifica esto significativamente.
Elegir el método correcto:
* CPU-Bound: Use `multiprocesamiento` o` concurrente.futures.processpoolexecutor`. Los procesos omiten el GIL y permiten el verdadero paralelismo.
* I/O-Bound: Use `concurrent.futures.threadpoolexecutor`. Los hilos son de peso más ligero que los procesos, y la sobrecarga de la conmutación de contexto es menor. Si la E/S es muy lenta, esto puede mejorar el rendimiento incluso con el GIL.
* Mixto: Si su bucle tiene partes unidas a CPU y unidas a E/S, es posible que necesite un enfoque más sofisticado, que combine potencialmente hilos y procesos o utilizando programación asincrónica (por ejemplo, `Asyncio`).
Consideraciones importantes:
* Overhead: La creación y la gestión de procesos o hilos introduce una sobrecarga. La paralelización solo proporciona un beneficio si el trabajo realizado por artículo es lo suficientemente sustancial como para superar esta sobrecarga.
* Compartir datos: Compartir datos entre procesos es más complejo que compartir datos entre hilos. Considere usar colas u otros mecanismos de comunicación entre procesos si es necesario.
* Depuración: El código paralelo de depuración puede ser un desafío. Comience con pequeños ejemplos y aumente gradualmente la complejidad.
Recuerde perfilar su código para medir la mejora del rendimiento después de la paralelización. Es posible que la paralelización no proporcione un beneficio significativo, o incluso ralentice las cosas, si la sobrecarga es demasiado alta o la tarea no es adecuada para la paralelización.