2012-07-26 13 views
9

Non è un segreto che su CUDA 4.x la prima chiamata a cudaMalloc può essere incredibilmente lento (che è stato segnalato più volte), apparentemente un bug nel driver CUDA.collegamento con le librerie CUDA 3rd party rallenta cudaMalloc

Recentemente, ho notato un comportamento strano: il tempo di esecuzione di cudaMalloc dipende direttamente da come molte librerie CUDA 3rd-party ho collegato al mio programma di (notare che io non utilizzare queste librerie, basta collegare il mio programma con loro)

ho corse alcuni test utilizzando il seguente programma:

int main() { 
    cudaSetDevice(0); 
    unsigned int *ptr = 0; 
    cudaMalloc((void **)&ptr, 2000000 * sizeof(unsigned int)); 
    cudaFree(ptr); 
return 1; 
} 

i risultati sono i seguenti:

  • Collegato con: 5,852449

  • Collegato con:: -lcudart -lnpp -lcufft -lcublas -lcusparse -lcurand tempo di esecuzione 1,425120

  • Collegato con: -lcudart -lnpp -lcufft -lcublas durata: -lcudart -lnpp -lcufft durata: 0.905424

  • collegato con: -lcudart durata: 0,394558

Secondo 'gdb', il tempo ind eed entra nel mio cudaMalloc, quindi non è causato da qualche routine di inizializzazione della libreria ..

Mi chiedo se qualcuno abbia una spiegazione plausibile per questo?

risposta

11

Nell'esempio, la chiamata cudaMalloc avvia la creazione del contesto pigro sulla GPU. Quando le librerie API di runtime sono incluse, i loro payload binari devono essere controllati e i simboli elfo della GPU e gli oggetti che contengono si fondono nel contesto. Più biblioteche ci sono, più tempo ci si può aspettare che il processo abbia. Inoltre, in caso di mancata corrispondenza dell'architettura in uno qualsiasi dei cubini e si dispone di una GPU compatibile con le versioni precedenti, è possibile anche attivare la ricompilazione del codice del dispositivo per la GPU di destinazione. In un caso molto estremo, ho visto una vecchia applicazione collegata a una vecchia versione di CUBLAS impiegare 10 secondi di tempo per caricare e inizializzare quando si esegue una GPU Fermi.

È possibile forzare esplicitamente contesto stabilimento pigro mediante emissione di cudaFree chiamata in questo modo:

int main() { 
      cudaSetDevice(0); 
    cudaFree(0); // context establishment happens here 
      unsigned int *ptr = 0; 
      cudaMalloc((void **)&ptr, 2000000 * sizeof(unsigned int));   
      cudaFree(ptr); 
    return 1; 
} 

Se profilo o uno strumento questa versione con timer si dovrebbe trovare che la prima cudaFree chiamata consuma la maggior parte del tempo di esecuzione e la La chiamata cudaMalloc diventa quasi gratuita.

+0

grazie a @talomnies, infatti l'inserimento di cudaFree all'inizio richiede tutto il tempo di esecuzione. Ho provato questo programma in origine sulla scheda grafica GT650M (core Kepler) mentre su GPU GTU5X Fermi ci vuole ancora più tempo - circa 7 secondi .. ancora NVIDIA potrebbe fare smth per ottimizzare la gestione del contesto - 7 secondi con carico di lavoro della CPU completo sembra essere troppo –

+0

@asm: prova CUDA 5 e guarda cosa fa. Ora c'è un linker di codice dispositivo appropriato nella catena di strumenti, quindi alcuni dei sovraccarichi in fase di esecuzione potrebbero essere spostati per compilare e collegare il tempo (o almeno un po 'semplificato). Inoltre, se hai trovato che questo ha risposto alla tua domanda, potresti essere così gentile da accettarlo in modo che la tua domanda sia contrassegnata come risposta. – talonmies

+0

Si noti che in CUDA 4.0, parte del motivo per cui l'inizializzazione CUDA richiede così tanto tempo è perché il driver sta eseguendo enormi allocazioni di memoria virtuale per l'indirizzamento virtuale unificato. – ArchaeaSoftware