16 puntos por GN⁺ 2025-08-08 | Aún no hay comentarios. | Compartir por WhatsApp
  • A medida que la ley de Moore llega a sus límites, el hardware ha evolucionado desde acelerar un solo núcleo hacia un enfoque centrado en múltiples núcleos y procesamiento paralelo
  • El procesamiento paralelo se divide en varias formas, como paralelismo de datos, paralelismo de modelo y paralelismo de canalización, y se usa de forma combinada en los sistemas modernos de aprendizaje profundo
  • La paralelización ocurre en varias capas, como SIMD (paralelismo de datos a nivel de instrucción), paralelismo de hilos/núcleos y paralelismo masivo en GPU
  • Las lenguajes, bibliotecas y herramientas para procesamiento paralelo son, en su mayoría, extensiones “agregadas” a lenguajes secuenciales existentes, por lo que está ganando atención la tendencia de integrar el paralelismo de forma nativa en el lenguaje (como Mojo)
  • La optimización práctica del rendimiento, como la optimización del uso compartido de líneas de caché (interacciones innecesarias), la partición eficiente de memoria y la vectorización automática, es una tarea clave

Motivación del paralelismo y evolución del hardware

  • Al principio, el rendimiento mejoraba de forma natural gracias a la miniaturización de transistores y al aumento de la frecuencia de reloj, pero se alcanzaron límites físicos por las restricciones térmicas y de fabricación
  • Después, la arquitectura multinúcleo se volvió el estándar, con decenas o incluso cientos de núcleos en una sola CPU

Formas generales de paralelismo

  • Paralelismo de datos: aplicar la misma operación a muchos datos al mismo tiempo (por ejemplo, suma de vectores)
  • Paralelismo de modelo: distribuir un modelo entre varios dispositivos
  • Paralelismo de canalización: dividir el cálculo en varias etapas para que cada una opere simultáneamente

SIMD (Single Instruction, Multiple Data) y vectorización

  • SIMD es un método para procesar varios datos (vectores) con una sola instrucción, y es compatible con varias ISA como ARM NEON y x86 SSE/AVX
  • Mediante intrinsics de C/C++ se puede controlar explícitamente la operación vectorial; el compilador también admite vectorización automática, aunque con limitaciones
  • En la práctica, se procesa repetidamente según la longitud del vector y luego los datos restantes se corrigen con operaciones escalares

Paralelización en CPU

  • Se aprovechan los hilos para ejecutar en paralelo sobre múltiples núcleos, con soporte del scheduler del SO y APIs según el lenguaje
  • Como el costo de crear y destruir hilos es alto, resulta eficiente dividir el trabajo con una cantidad adecuada de hilos en relación con el tamaño de los datos (similar al número de núcleos)
  • Es importante optimizar el 'false sharing' de líneas de caché (degradación de rendimiento cuando distintos hilos acceden a variables independientes dentro de la misma línea de caché); pueden usarse herramientas como std::hardware_destructive_interference_size de C++17
  • Es necesario aplicar padding/alineación para que cada hilo escriba en una región de datos separada

Paralelización en GPU

  • La GPU está especializada en procesamiento paralelo masivo de datos mediante miles de núcleos pequeños
  • CUDA/OpenCL: ejecuta funciones kernel en unidades de decenas hasta decenas de miles de hilos/bloques; internamente usa el modelo SIMT (Single Instruction, Multiple Threads)
  • El funcionamiento por unidades de work group/warp y la minimización de la divergencia de ramas (branch divergence) son extremadamente importantes para el rendimiento
  • Jerarquía de memoria: se requiere optimización por niveles entre registros de hilo, memoria compartida por bloque y memoria global total

Triton: DSL de kernels GPU basado en Python

  • Triton es un DSL integrado en Python, con soporte para compilación JIT y múltiples backends (MLIR/LLVM/PTX, etc.)
  • Permite escribir código kernel en Python de alto nivel, con soporte para paralelización, partición y enmascaramiento automáticos
  • Logra entre 75% y 90% del rendimiento de NVIDIA cuDNN, mientras reduce drásticamente la complejidad de desarrollo

Paralelismo nativo en el lenguaje: Mojo

  • Mojo es un nuevo lenguaje creado por Chris Lattner, desarrollador de LLVM/MLIR, que admite paralelismo y compilación especializada para hardware a nivel de lenguaje
  • Los tipos vectoriales SIMD, las funciones vectorizadas y la distinción entre memoria de host/dispositivo muestran que el paralelismo está integrado en el sistema de tipos y en la estructura del lenguaje
  • Incluso los bucles con estilo Python pueden vectorizarse automáticamente, lo que permite obtener rendimiento sin control explícito de bajo nivel

Conclusión y perspectivas

  • La programación paralela moderna surge de la combinación de distintos hardwares y modelos de paralelismo, y el soporte del propio lenguaje se vuelve cada vez más importante
  • Con el auge de lenguajes y herramientas de paralelismo de nueva generación como Mojo, Triton y JAX, la paralelización está evolucionando para ser más intuitiva y productiva
  • La programación paralela puede maximizar el rendimiento real solo cuando la arquitectura del hardware, la optimización de memoria y el soporte del lenguaje se combinan de forma orgánica

Aún no hay comentarios.

Aún no hay comentarios.