Uso CUDA da alcune settimane, ma ho alcuni dubbi sull'assegnazione di blocchi / orditi / filo. Sto studiando l'architettura da un punto di vista didattico (progetto universitario), quindi raggiungere le massime prestazioni non è una mia preoccupazione.
Prima di tutto, vorrei capire se ho capito bene questi fatti:
Il programmatore scrive un kernel e organizza la sua esecuzione in una griglia di blocchi di thread.
Ogni blocco è assegnato a un multiprocessore di streaming (SM). Una volta assegnato, non può migrare verso un altro SM.
Ogni SM suddivide i propri blocchi in Warps (attualmente con una dimensione massima di 32 thread). Tutti i thread in un ordito vengono eseguiti simultaneamente sulle risorse dell'SM.
L'esecuzione effettiva di un thread viene eseguita dai core CUDA contenuti nell'SM. Non esiste un mapping specifico tra thread e core.
Se un ordito contiene 20 thread, ma attualmente ci sono solo 16 core disponibili, il warp non verrà eseguito.
D'altra parte, se un blocco contiene 48 thread, verrà suddiviso in 2 orditi e verranno eseguiti in parallelo a condizione che sia disponibile memoria sufficiente.
Se un thread inizia su un core, viene bloccato per l'accesso alla memoria o per un'operazione in virgola mobile lunga, la sua esecuzione potrebbe riprendere su un core diverso.
Sono corretti?
Ora ho una GeForce 560 Ti, quindi secondo le specifiche è dotata di 8 SM, ciascuna contenente 48 core CUDA (384 core in totale).
Il mio obiettivo è assicurarsi che ogni nucleo dell'architettura esegua le stesse istruzioni. Supponendo che il mio codice non richiederà più registri di quelli disponibili in ogni SM, ho immaginato approcci diversi:
Creo 8 blocchi di 48 thread ciascuno, in modo che ogni SM abbia 1 blocco da eseguire. In questo caso i 48 thread verranno eseguiti in parallelo nell'SM (sfruttando tutti i 48 core disponibili per loro)?
C'è qualche differenza se lancio 64 blocchi di 6 thread? (Supponendo che saranno mappati uniformemente tra gli SM)
Se "sommergo" la GPU nel lavoro pianificato (creando 1024 blocchi di 1024 thread ciascuno, ad esempio) è ragionevole supporre che tutti i core verranno utilizzati ad un certo punto e eseguirò gli stessi calcoli (supponendo che i thread mai in stallo)?
Esiste un modo per verificare queste situazioni utilizzando il profiler?
C'è qualche riferimento per questa roba? Ho letto la guida alla programmazione CUDA e i capitoli dedicati all'architettura hardware in "Programmazione di processori paralleli massicci" e "Progettazione e sviluppo di applicazioni CUDA"; ma non sono riuscito a ottenere una risposta precisa.