2016-06-19 63 views
8

Sto appena iniziando a utilizzare il pacchetto CUDArt di Julia per gestire l'elaborazione in GPU. Mi chiedo come garantire che se vado a estrarre dati dalla gpu (ad esempio usando to_host()) che non lo faccio prima che tutti i calcoli necessari siano stati eseguiti su di esso.Come sincronizzare con Julia CUDArt?

Attraverso alcuni esperimenti, sembra che to_host(CudaArray) rimarrà in ritardo mentre il particolare CudaArray viene aggiornato. Quindi, forse basta usare questo è sufficiente per garantire la sicurezza? Ma sembra un po 'rischioso.

In questo momento, sto utilizzando la funzione launch() per eseguire i miei kernel, come illustrato nel pacchetto documentation.

La documentazione di CUDArt fornisce un esempio utilizzando la macro @sync di Julia, che potrebbe sembrare deliziosa. Ma per gli scopi di @sync ho finito con il mio "lavoro" e pronto a passare non appena il kernel viene lanciato con launch(), non una volta che finisce. Per quanto comprendo l'operazione di launch() - non c'è un modo per cambiare questa funzione (ad es. Per farlo attendere di ricevere l'output della funzione "lancia").

Come posso eseguire tale sincronizzazione?

risposta

1

Penso che il modo più canonica è quello di rendere un flusso per ogni dispositivo:

streams = [(device(dev); Stream()) for dev in devlist]

e poi all'interno del blocco @async, dopo gli si dice di fare i calcoli, si utilizza la funzione wait(stream) a ditelo per aspettare che il flusso finisca i suoi calcoli. Vedere l'esempio degli stream nel README.

+0

Buon punto. Penso che 'device_synchronize' possa ancora essere utile in una serie di impostazioni. 1. Puoi usarlo insieme ad altre funzioni, come quelle di CUBLAS, CUSPARSE, ecc. Che non prendono flussi come argomenti. Inoltre, se stai lavorando con una singola GPU, potresti addirittura non aver bisogno di streaming, e quindi 'device_synchronize' può portare a un'applicazione un po 'più semplice. –

10

Ok, quindi, non c'è un sacco di documentazione sul pacchetto CUDArt, ma ho guardato il codice sorgente e penso che sia semplice su come farlo. In particolare, sembra che ci sia una funzione device_synchronize() che bloccherà fino a quando non sarà terminato tutto il lavoro sul dispositivo attualmente attivo. Così, quanto segue, in particolare, sembra funzionare:

using CUDArt 
md = CuModule("/path/to/module.ptx",false) 
MyFunc = CuFunction(md,"MyFunc") 
GridDim = 2*2496 
BlockDim = 64 
launch(MyFunc, GridDim, BlockDim, (arg1, arg2, ...)); 
device_synchronize() 
res = to_host(arg2) 

mi piacerebbe sentire da qualcuno con più esperienza anche se non v'è qualcosa di più di essere a conoscenza di qui.

+7

Solo una parola di cautela: le funzioni non documentate possono essere lì per uso interno (quindi la mancanza di documentazione). Ovviamente questo non è sempre il caso, ma, se si utilizzano queste funzioni, è possibile impostare se stessi per problemi durante l'aggiornamento alla versione successiva. I proprietari di pacchetti e librerie tendono a sentirsi più a proprio agio a causa di modifiche o rimostruzioni definitive delle funzionalità non documentate, anche tra rilasci minori. Procedere con cautela e assicurarsi di scrivere test di regressione. – JDB