Saltar al contenido principal

Práctica 2: DataLoader concurrente para aprendizaje profundo

Fecha límite de entrega: 3 de noviembre de 2026 a las 15:00
Lenguaje de trabajo: Python (threading, multiprocessing, queue)
Código de inicio: 📥 p2_dataloader.zip


1. Objetivos de la práctica​

  1. Diseñar e implementar una solución concurrente libre: Diseñar una arquitectura de datos concurrente en Python para optimizar la preparación de imágenes en modelos de aprendizaje profundo.
  2. Identificar cuellos de botella I/O vs. CPU: Analizar la naturaleza de cada fase del pipeline (lectura de disco, decodificación PIL, transformaciones de imagen) y elegir las herramientas concurrentes más adecuadas (threading, multiprocessing, queue).
  3. Evaluar el rendimiento y la corrección: Medir experimentalmente la ganancia de velocidad (throughput en imágenes por segundo) garantizando la ausencia de condiciones de carrera, deadlocks o fugas de memoria.

2. El problema: canalización de datos en aprendizaje profundo​

En el entrenamiento de redes neuronales de visión por computador, la preparación de los datos (lectura de ficheros desde disco, decodificación de imagen, recortado y transformaciones) ocurre mientras el modelo entrena con los lotes (batches) de datos.

Si la preparación de imágenes se realiza de forma secuencial síncrona, el bucle de entrenamiento se frena constantemente esperando a que la CPU termine de procesar la siguiente imagen (I/O & CPU Bottleneck).

El objetivo de esta práctica es diseñar e implementar un DataLoader concurrente que ejecute la preparación de imágenes en paralelo y solape este trabajo con el consumo de lotes.


3. Código base de la práctica​

Descarga el paquete comprimido de partida:
📥 p2_dataloader.zip

El paquete contiene la implementación secuencial de partida y el script de evaluación:

  • dataloader_seq.py: Implementación secuencial de referencia (DataLoaderSeq).
  • train.py: Script de entrenamiento que simula el consumo de lotes y mide el rendimiento (throughput en img/s).
  • download_imagenette_dataset.sh: Script para descargar y descomprimir el dataset Imagenette2.
  • requirements.txt: Dependencias del proyecto (pillow, tqdm, numpy).

Preparación del entorno:​

# 1. Instalar dependencias
pip install -r requirements.txt

# 2. Descargar y descomprimir el dataset Imagenette2
bash download_imagenette_dataset.sh

# 3. Ejecutar la versión secuencial de partida
python train.py

4. Descripción del trabajo a realizar​

Debes diseñar e implementar una nueva versión concurrente de la clase DataLoader (por ejemplo, en un archivo dataloader_mp.py) que reemplace a la versión secuencial y mejore sustancialmente el rendimiento (throughput en imágenes/segundo).

Libertad de diseño e investigación​

No se impone una arquitectura rígida ni un patrón de diseño predeterminado. Como estudiante, debes investigar, evaluar y decidir qué modelo de concurrencia y qué estructuras de datos son las más apropiadas para este problema.

Entre las herramientas del lenguaje Python que puedes considerar y combinar se encuentran:

  • Módulos de concurrencia: threading (hilos) y multiprocessing (procesos).
  • Estructuras de datos y comunicación: queue.Queue, multiprocessing.Queue, Pipe, Event, Lock, Semaphore, etc.
  • Gestores de tareas y pools: multiprocessing.Pool o concurrent.futures.

5. Requisitos de la solución​

  1. Transparencia de la interfaz: Tu DataLoader debe mantener la misma interfaz de consumo y poder usarse en train.py sin modificar el bucle principal (for batch in dataloader:).
  2. Correctitud:
    • Sin pérdidas ni duplicados: Cada imagen del dataset debe procesarse exactamente una vez por época (o floor(N / batch_size) lotes si drop_last=True).
    • Cierre determinista y limpio: Al finalizar la iteración o al interrumpir el programa, todos los hilos y procesos deben cerrarse limpiamente sin dejar procesos colgados (zombies) ni deadlocks.
  3. Control de recursos y memoria: Evitar acumular involuntariamente un número ilimitado de datos en memoria RAM durante la ejecución.

6. Cuestiones a responder en la memoria​

En tu documento de entrega (memoria.pdf o memoria.md) debes incluir:

  1. Diseño de la arquitectura: Describe la arquitectura concurrente que has diseñado (mecanismos elegidos, sincronización o comunicación de datos y flujo de trabajo) mediante un esquema o diagrama explicativo.
  2. Tabla comparativa de rendimiento: Compara el tiempo total (segundos) y el throughput (imágenes/segundo) registrados en train.py entre la versión secuencial (DataLoaderSeq) y tu versión concurrente.
  3. Justificación de decisiones técnicas: Explica por qué elegiste hilos, procesos o combinaciones de ambos para cada parte del trabajo, y cómo influyó el Global Interpreter Lock (GIL) de Python en tus decisiones.
  4. Análisis de parámetros: Muestra los resultados obtenidos al variar los parámetros de tu solución (número de hilos/procesos, tamaños de buffer o cola, etc.) e identifica dónde se encontraba el principal cuello de botella.
  5. Distribución temporal del uso de CPU: Analiza la carga de los núcleos de la CPU a lo largo del tiempo durante la ejecución (mediante capturas de monitor del sistema, htop o librerías como psutil), comparando cómo se distribuye el trabajo en la versión secuencial frente a tu versión concurrente.
Medición del uso de CPU

Para recopilar datos o capturas del uso de la CPU por núcleo en Python, puedes usar la librería psutil (incluida en requirements.txt). El script train.py del código base incluye unas líneas opcionales comentadas que muestran cómo muestrear psutil.cpu_percent(interval=1, percpu=True) en un hilo en segundo plano. También puedes usar herramientas visuales del sistema como htop, btop o el Monitor de Actividad.


7. Criterios de evaluación y entrega​

La entrega se realizará en la plataforma pracdlsi en un archivo comprimido denominado p2.tgz.

El archivo comprimido debe incluir:

  1. memoria.pdf (o memoria.md): Informe con la descripción del diseño, diagramas, tablas de rendimiento y respuestas a las cuestiones.
  2. dataloader_mp.py (y archivos auxiliares): Código fuente de tu DataLoader concurrente.
  3. train.py: Script ajustado para evaluar tu solución.