2013-06-05 12 views
7

Sto provando a cambiare un algoritmo che avevo scritto da un processore Tesla T10 (capacità di calcolo 1.3) a un Tesla M2075 (capacità di calcolo 2.0). Durante il passaggio sono rimasto sorpreso nel constatare che il mio algoritmo ha rallentato. L'ho analizzato e ho scoperto che sembra essere perché sulla nuova macchina i flussi di cuda stanno bloccando. Il mio algoritmo ha 3 attività principali che possono essere suddivise ed eseguite in parallelo: riorganizzazione della memoria (che può essere eseguita sulla CPU), copia della memoria dall'host al dispositivo e esecuzione del kernel sul dispositivo. Sul vecchio splitting macchina i flussi consentiti i 3 compiti si sovrappongono come questo (tutte le immagini dalla NVidia visiva Profiler): Correct stream executionCome determinare il motivo per cui uno stream CUDA sta bloccando

Tuttavia sulla nuova macchina il blocco corsi d'acqua prima di iniziare il calcolo della CPU fino a quando il kernel precedente è fatto l'esecuzione, come si può vedere qui: 3 stream execution

potete vedere la riga superiore, tutti i blocchi arancioni sono il cudaStreamSynchronize chiama quale blocco fino a quando il kernel precedente è fatto l'esecuzione, anche se questo kernel è su un flusso completamente diverso. Sembra funzionare per la prima volta attraverso i flussi e parallelizza correttamente, ma dopo inizia il problema, quindi ho pensato che forse stava bloccando qualcosa e ho cercato di aumentare il numero di flussi che mi hanno dato questo risultato: 12 stream execution

Qui si può vedere che per qualche motivo solo i primi 4 flussi stanno bloccando, dopodiché inizia a parallelizzare correttamente. Come ultimo tentativo ho cercato di aggirarlo usando solo i primi 4 stream per una sola volta e poi passando a utilizzare i flussi successivi ma non funzionava ancora e si bloccava ancora ogni 4 flussi lasciando che gli altri stream venissero eseguiti simultaneamente : 10 stream execution

Quindi sto cercando idee su cosa potrebbe causare questo problema e su come diagnosticarlo. Ho studiato il mio codice e non penso che sia un bug lì, anche se potrei sbagliarmi. Ogni stream è incapsulato nella propria classe e ha solo un riferimento a un singolo cudaStream_t che è un membro di quella classe, quindi non vedo come potrebbe fare riferimento a un altro stream e a bloccarlo.

Ci sono dei cambiamenti nel modo in cui gli stream funzionano tra la versione 1.3 e 2.0 di cui non sono a conoscenza? Potrebbe essere qualcosa con la memoria condivisa non essere liberata e dover aspettare su quello? Qualsiasi idea su come diagnosticare questo problema è gradita, grazie.

+1

Mi chiedo se il problema potrebbe essere lo stesso di quello recentemente discusso nella discussione seguente nei forum NVIDIA: https: //devtalk.nvidia.com/default/topic/545476/cuda-programming-and-performance/cuda-stream-performance/La soluzione è stata aggiungere l'opzione 'conckerneltrace' all'impostazione del profiler. – njuffa

+1

windows o linux? quale versione di driver stai usando in ogni caso? quali sono i parametri di lancio per i tuoi kernel? puoi pubblicare un riproduttore di qualche tipo? –

+0

In NVIDIA Visual Profiler (CUDA 5.0 e 5.5), esiste anche un'opzione 'Abilita profilo di kernel simultaneo'. Suppongo che questo ottenga gli stessi risultati dell'opzione CLI 'conckerneltrace'. Nota che hai bisogno di un dispositivo CC> = 2.0 per quello. – BenC

risposta

3

Non posso essere completamente sicuro di non vedere il codice, ma sembra che tu stia riscontrando un problema con l'ordine in cui accodati i tuoi comandi. C'è una leggera differenza nel modo in cui i dispositivi 1.x e 2.x di capacità di elaborazione gestiscono i flussi a causa del fatto che i dispositivi 2.x possono eseguire più kernel simultaneamente e gestire contemporaneamente sia HtoD che DtoH.

Se si accodano i comandi nell'ordine tutti gli HtoD, tutti i calcoli, tutti i DtoHs avranno buoni risultati sulle schede Tesla (1060 et. Al.).

Se ordinate copia HtoD, calcola, copia DtoH, copia HtoD ... ecc. Otterrai buoni risultati su Fermi.

Keplero fa altrettanto bene in entrambi i casi. Questo è importante attraverso i flussi in entrambi i casi di Tesla e Fermi, suggerisco di leggere this NVIDIA post per ulteriori informazioni. Sovrapporre i flussi può essere un problema estremamente complicato, ti auguro ogni bene. Se si desidera ulteriore aiuto, una rappresentazione generale dell'ordine in cui si accodano le operazioni sarebbe estremamente utile.