El modelo de programación en CUDA asume que todos los threads se ejecutan en un dispositivo separado del host que ejecuta la aplicación. Por lo tanto se mantiene implícita la suposición que el host y los dispositivos mantienen sus propios espacios de memoria separados, referidos como la memoria del host (RAM) y la del dispositivo, el cual a su vez está conformado por registros, memoria local, memoria compartida, memoria global, o constantes, como se ve en la siguiente figura:
Cada thread puede:
- Leer/escribir en registros por thread.
- Leer/escribir en memoria local por thread.
- Leer/escribir en memoria compartida por bloque.
- Leer/escribir en memoria global por grid.
- Sólo lectura en memoria constante por grid.
Reglas en el manejo de memoria:
- Actualmente sólo se puede transferir datos desde el host a la memoria global (y memoria constante) y no directamente del host a la memoria compartida.
- La memoria constante se usa para datos que no cambian (por ejemplo, leídas sólo por la GPU).
- La memoria compartida llega a tener una velocidad 15x de la memoria global.
- Los registros tienen velocidad similar a la memoria compartida si lee la misma dirección o no hay conflictos.
Tiempo de vida y alcances de la memoria en CUDA
- __device__ es opcional cuando se usa con __local__, __shared__, o __constant__
- Las variables sin identificador residen automáticamente en un registro. Excepto los arrays que residen en memoria local.
- Las variables escalares residen en registros on-chip de alta velocidad.
- Las variables compartidas residen en memorias on-chip de alta velocidad.
- Los arrays locales a un thread y las variables globales residen en memoria off-chip sin caché.
- Las constantes residen en memoria off-chip sin caché.