.. | ||
a_multip.py | ||
b_multit.py | ||
README.md |
Threading y Multiprocessing
Con Threading y Multiprocessing, se puede ejecutar código en paralelo y
mejorar los tiempos de ejecución.
Ejemplos:
Process / Proceso:
Una instancia de un programa (ej, el interprete de Python)
- Aprovecha multiples CPUs y Nucleos.
- Espacios de memoria separados -> memoria no compartida entre procesos
- Genial para procesamiento dependiente de la CPU (CPU-bound processing)
- Nuevos procesos son independientes de otros procesos
- Los procesos son interruptable/killable
- Un GIL para cada proceso -> evita las limitaciones GIL
- Son pesados y utilizan mas memoria
- Iniciar un proceso es mas lento que iniciar un thread
- IPC (inter-process communication) es mas complicada
Threads / Hilo:
Una entidad en/dentro de un proceso que puede ser programado (también conocido como 'proceso liviano')
Un proceso puede generar multiples hilos.
- Todos los hilos dentro de un proceso comparten la misma memoria
- Son mas livianos
- Uniciar un hilo es mas rápido que iniciar un proceso
- Buenos para tareas 'I/O-bound' (tareas de entrada y salida, ej. hdd, network)
- Los hilos son limitados por GIL: Solo un hilo a la vez
- Sin efecto para tareas 'CPU-bond' (cpudependientes)
- No son interruptable/killable
- Se debe tener cuidado con condiciones de carrera (cuando 2 o mas hilos necesitan
modificar la misma variable al mismo tiempo)
GIL: Global Interpreter Lock
- Es un bloqueo que solo permite la ejecución de un hilo a la vez en python
- Es necesaria en CPython porque la administración de memoria no es 'thread-safe'
Para evitar GIL:
- Usar multiprocessing
- Utilizar una implementación de Python diferente, 'free-threaded' (Jython, IronPython)
- Usar Python como un envoltorio para librerias de terceros (C/C++) -> numpy, scipy
Multiprocessing
from multiprocessing import Process
import os, time
def nros_cuadrados():
"""
función dummy para ser ejecutada por Process 'target'
"""
for i in range(100):
i * i
time.sleep(0.1)
# lista que guarda todos los procesos
procesos = []
# un buen número de procesos es la cantidad de CPUs de la maquina
num_procesos = os.cpu_count()
# creación de los procesos
for i in range(num_procesos):
# Process toma 2 argumentos
# función target
p = Process(target=nros_cuadrados) # , args=(tupla_args))
procesos.append(p)
# Iniciar procesos
for p in procesos:
p.start()
# join (bloquear el hilo principal hasta terminar ejecución de procesos)
for p in procesos:
p.join()
print("FIN main")
Ejemplo de la salida de Htop
20551 root 20 0 8732 S 0.0 0.1 0:00.00 1 python3 multi.py
20552 root 20 0 8732 S 0.0 0.1 0:00.00 1 python3 multi.py
20553 root 20 0 8732 S 0.0 0.1 0:00.00 1 python3 multi.py
20554 root 20 0 8732 S 0.0 0.1 0:00.00 1 python3 multi.py
20555 root 20 0 8732 S 0.0 0.1 0:00.00 1 python3 multi.py
20556 root 20 0 8732 S 0.0 0.1 0:00.00 1 python3 multi.py
20557 root 20 0 8736 S 0.0 0.1 0:00.00 1 python3 multi.py
20558 root 20 0 8736 S 0.0 0.1 0:00.00 1 python3 multi.py
Threading
from threading import Thread
import os, time
def nros_cuadrados():
"""
función dummy para ser ejecutada por Thread 'target'
"""
for i in range(100):
i * i
time.sleep(0.1)
# lista que guarda todos los threads
hilos = []
num_hilos = 10
# creación de los hilos
for i in range(num_hilos):
# Thread toma 2 argumentos
# función target
h = Thread(target=nros_cuadrados) # , args=(tupla_args))
hilos.append(h)
# Iniciar hilos
for h in hilos:
h.start()
# join (bloquear el hilo principal hasta terminar ejecución de procesos)
for h in hilos:
h.join()
print("FIN main")
Ejemplo de la salida de Htop
23903 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23904 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23905 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23906 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23907 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23908 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23909 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23910 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23911 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py
23912 root 20 0 8732 S 0.0 0.1 0:00.00 11 python3 b_multit.py