#3 - 100 Taladores, 1 Meta: Paralelización en el mundo de la computación
Qué son las GPUs y por qué están tomando el protagonismo en la computación de alto rendimiento y la inteligencia artificial.
Imagina que tuvieras que talar 100 árboles lo más rápido posible y te dieran las siguientes opciones:
Contratar al mejor talador del mundo y darle la mejor hacha del mundo.
Contratar a 100 taladores mediocres equipados con hachas mediocres.
Si la métrica de éxito es la rapidez, la segunda opción será muy probablemente la mejor. Y esto es porque se paraleliza la tarea. Todos los árboles se pueden talar a la vez.
En el mundo de la computación también aparece este fenómeno de la paralelización y quiero mostrarte un ejemplo práctico para que observes sus beneficios y entiendas porqué esta industria está en auge.
El poder computacional como activo
En los últimos años ha explotado la demanda de poder computacional.
Tecnologías como Bitcoin o la IA están totalmente apalancadas en la potencia de cómputo.
En el caso de Bitcoin se utiliza principalmente en el proceso de minado.
En el caso de la IA es fundamental tanto para entrenar modelos como para su posterior utilización.
No es casualidad que empresas que se dedican a la fabricación de hardware especializado en computación (típicamente GPUs), como NVIDIA, hayan experimentado un crecimiento notable en bolsa.
De hecho, mientras escribo estas líneas NVIDIA es la mayor empresa por capitalización bursátil de EEUU. Por encima de Microsoft, Apple, Meta, Alphabet y Amazon.
Pero, ¿Qué son las GPUs? ¿Por qué son tan valiosas? ¿Qué aportan en este nuevo paradigma tecnológico?
Veámoslo.
Conceptos clave sobre los componentes de un PC
Seguro que alguna vez has comprado un ordenador y te has encontrado con muchos datos que no siempre has entendido. A mi también me ha pasado. Te voy a contar los elementos clave, especialmente pensando en la potencia computacional.
El procesador o CPU (Central Processing Unit)
Es el cerebro del ordenador. Se encarga fundamentalmente de realizar cálculos. Por ejemplo, cuando estás programando y haces a=2+2, el procesador hace la suma y almacena la variable a con valor 4 en la memoria RAM (luego la comentaremos).
Estas tareas las realizan concretamente los núcleos (o cores) del procesador. Podemos entender un núcleo como un trabajador al que le podemos encargar tareas.
Nos interesa que nuestra CPU tenga el máximo número de trabajadores y lo más rápidos posibles (la velocidad de cada núcleo se mide en GHz).
Por ejemplo, un MacBook Pro con Chip M1 Pro tiene 10 núcleos de ~3 GHz.
Memoria RAM (Random Access Memory)
Almacena la información a corto plazo que el procesador está utilizando en ese momento.
Para que lo veas más claro: cuando abres un archivo Word, lo que ocurre es que se hace una copia de la información desde el disco duro (que es una memoria permanente) a la memoria RAM. Mientras estás trabajando con el documento estás interaccionando con la memoria RAM (por eso la interacción es muy rápida). Cuando cierras el Word y guardas los cambios, estos se actualizan en el disco duro (donde quedan guardados permanentemente) y la información se borra de la RAM.
Lo más característico de la RAM es que permite escribir y leer extremadamente rápido (esto se mide en GB/s). Es lo que hace que puedas utilizar de forma fluida diferentes aplicaciones simultáneamente.
Nos interesa que está memoria sea lo más grande posible y lo más rápida posible.
Tarjeta Gráfica
De forma simplifica, una tarjeta gráfica es como un ordenador que está dentro de un ordenador.
Tiene su propia unidad de procesamiento, Graphics Processing Unit o GPU, que sería algo así como la prima (lejana) de la CPU del ordenador.
Importante: la GPU es uno de los componentes de la tarjeta gráfica, no es la tarjeta gráfica en sí. Tienden a asociarse porque las tarjetas gráficas más potentes del mercado se apalancan precisamente en el uso de GPU.
En cualquier caso, lo importante es que la GPU, al igual que la CPU, también tiene núcleos, que son los encargados de realizar las tareas dentro de la tarjeta gráfica.
Además, la tarjeta gráfica también tiene una memoria RAM propia (aunque se hace llamar VRAM) con la que interacciona la GPU. Normalmente esta VRAM tiene menos capacidad que la RAM del ordenador, pero es mucho más rápida.
Te muestro a continuación el caso real de mi ordenador para que podamos comentar las diferencias.
La GPU de la tarjeta gráfica tiene muchos más núcleos que la CPU, pero son algo más lentos. Podríamos decir que la CPU tiene unos pocos trabajadores, muy listos y rápidos, que trabajan de forma secuencial, pero la tarjeta gráfica tiene un maldito ejercito de trabajadores, que son menos eficientes individualmente, pero que están perfectamente coordinados para trabajar en paralelo.
Comparativa en Python: CPU vs GPU
La tarjeta gráfica (o más bien, la GPU) y su ejercito de núcleos permite paralelizar las tareas de cálculo.
Para ilustrarlo vamos a realizar un ejercicio muy simple usando Python.
Vamos a multiplicar dos matrices (A y B) de 20.000 x 20.000. El resultado será otra matriz (C) de 20.000 x 20.000 elementos.
Quizá tengas en el olvido cómo multiplicar 2 matrices pero la cuestión es que si quisieras hacer este ejercicio a mano tendrías que hacer:
8.000.000.000.000 sumas.
8.000.000.000.000 multiplicaciones.
Inabarcable a mano.
En Python lo vamos a hacer a través de dos librerías:
Numpy, que es muy eficiente multiplicando matrices pero no usa paralelización. Este caso solo utiliza un núcleo del procesador para calcular.
Cupy1, que es casi idéntica a Numpy, pero pensada para usar la GPU y paralelizar el cálculo.
Aquí te dejo el código. Si sabes un poco de Python no requiere explicación porque es trivial. Si no, da igual, ignora el código y sigue leyendo.
La comparativa de tiempo se explica por si sola.
Paralelizando hemos dividido aproximadamente entre 100 el tiempo de ejecución.
De hecho, si repetimos el experimento pero con matrices de 10.000 elementos el resultado es aun más exagerado.
Ojo, no todas las tareas se benefician de paralelizar. Este caso es muy obvio ya que, por ejemplo, podríamos imaginarnos diferentes núcleos encargándose de calcular diferentes elementos de la matriz resultante. Esto ocurre porque se puede calcular cada elemento de forma independiente (de la misma forma que se pueden talar muchos árboles a la vez).
Pero imagina un cálculo iterativo donde cada iteración dependiese del resultado de la iteración anterior. En este caso es más complejo aprovechar la paralelización porque se trata de un proceso secuencial que, si o si, requiere esperar a que termine la iteración anterior para empezar una nueva.
En cualquier caso, la moraleja de todo esto es que el uso de GPU operando en paralelo permite disminuir drásticamente los tiempos de cómputo de muchas tareas:
Entrenar modelos de IA gigantescos en tiempos razonables.
Obtener respuesta de LLMs en cuestión de segundos.
Que tus videojuegos se ejecuten correctamente en tu PC.
Ganar la carrera del minado de Bitcoin.
Y en definitiva esto es lo que explica el gran valor de esta tecnología y el auge del mercado de GPU.
PD: En la edición #2 - Hackeando la Quiniela, ya escribí sobre un proyecto donde la paralelización fue clave. Aunque se lograba a través del uso de multitud de CPUs en un entorno Cloud en lugar de utilizando GPUs en local.
Muchas gracias por leer Ochenta Veinte!
Si te ha aportado valor y quieres más, puedes suscribirte aquí:
Y si ya eres suscriptor y quieres echarme una mano, puedes compartir el post:
Hasta la próxima
Álvaro OPK
Cupy se puede instalar como una librería cualquiera de Python. No obstante, necesitas una tarjeta gráfica con GPU de NVIDIA compatible con CUDA. En caso de que la tengas, antes de instalar Cupy necesitas instalar el toolkit de CUDA (puedes encontrarlo en la página oficial de NVIDIA).