Una GPU reparte 14 elementos entre 16 hilos
Una GPU (unidad de procesamiento gráfico) es un procesador con miles de hilos pequeños que ejecutan a la vez la misma función sobre datos distintos. Los hilos se organizan en bloques, y los bloques en una rejilla.
Entender esa organización permite saber qué elemento le toca a cada hilo. En este laboratorio no hay GPU: la rejilla se simula en Python.
Al final de esta lección
Nota
Puedo calcular qué elemento procesa cada hilo de una rejilla de bloques.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Hilo | un trabajador pequeño que procesa un elemento |
| Bloque | un grupo de hilos que se lanzan juntos |
| Rejilla | el conjunto de todos los bloques de un lanzamiento (en inglés, grid) |
| Índice global | el número del elemento que le toca a un hilo |
| Hilo ocioso | un hilo cuyo índice cae fuera de los datos |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Una GPU usa muchos hilos sencillos
Un procesador normal tiene pocos núcleos muy potentes. Una GPU tiene miles de núcleos sencillos. Cada hilo hace una tarea pequeña, por ejemplo sumar dos números.
Todos los hilos ejecutan la misma función. Cada uno toma un elemento distinto de los datos. Es la idea de la lección anterior, llevada al extremo.
Hilos en bloques, bloques en una rejilla
Un lanzamiento tiene dos números. El tamaño del bloque dice cuántos hilos tiene cada bloque. El número de bloques dice cuántos bloques forman la rejilla.
Cada hilo conoce dos cosas: en qué bloque está y qué posición ocupa dentro de él. Con esas dos cosas puede saber cuál es su elemento.
Índice global: bloque por tamaño más hilo
Para saber su elemento, un hilo calcula: índice global = bloque × tamaño del bloque + hilo.
Con bloques de 4 hilos, el hilo 1 del bloque 2 trabaja el elemento 2 por 4 más 1, es decir, el 9. Los bloques se reparten los elementos en orden, y dentro de cada bloque, los hilos también.
Ejemplo: 14 elementos con bloques de 4 hilos
| Bloque | Hilo | Cuenta | Índice global | Qué hace |
|---|---|---|---|---|
| 0 | 0 | 0 × 4 + 0 | 0 | Trabaja el elemento 0 |
| 1 | 3 | 1 × 4 + 3 | 7 | Trabaja el elemento 7 |
| 2 | 1 | 2 × 4 + 1 | 9 | Trabaja el elemento 9 |
| 3 | 1 | 3 × 4 + 1 | 13 | Trabaja el elemento 13 |
| 3 | 2 | 3 × 4 + 2 | 14 | Está ocioso: no hay elemento 14 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Recorrer una rejilla simulada
# Una rejilla simulada: 2 bloques de 3 hilos, sobre 5 elementos.
tam_bloque = 3
bloques = 2
n = 5
for bloque in range(bloques):
for hilo in range(tam_bloque):
indice = bloque * tam_bloque + hilo
if indice < n:
print("bloque", bloque, "hilo", hilo, "-> trabaja el elemento", indice)
else:
print("bloque", bloque, "hilo", hilo, "-> índice", indice, "sobra")
# Cambia tam_bloque a 2 y bloques a 3: ¿qué hilos sobran?
Sobran hilos cuando los datos no encajan
Los bloques se piden enteros. Para 14 elementos con bloques de 4 hacen falta 4 bloques, es decir, 16 hilos. Los 2 hilos que sobran son ociosos y no hacen nada.
El número de bloques es la división de elementos entre tamaño, redondeada hacia arriba. Se calcula con (n + tamaño - 1) // tamaño.
Qué imprime el script del laboratorio
El laboratorio trae steps/kernel.py. Simula un lanzamiento de 3 bloques de 4 hilos sobre una lista de 10 elementos. Cada línea dice el bloque, el hilo y el índice global.
Las palabras que imprime están en inglés, como block, thread y global index. Los hilos con índices 10 y 11 sobran. El script no se modifica en esta lección.
Ver un lanzamiento de 3 bloques de 4
docker exec jupyter python3 steps/kernel.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Cuántos bloques enteros caben en 10
docker exec jupyter python3 -c "print(divmod(10, 4))"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error muy común
Advertencia
Mucha gente cree que, si hay 10 elementos y bloques de 4, bastan 2 bloques. Dos bloques cubren 8 elementos y dejan 2 sin hilo. Hay que redondear hacia arriba, y proteger a los hilos que sobran con una comprobación: si el índice es menor que n, trabaja.