2012-03-16 14 views
6

Sto lavorando a un programma accelerato GPU che richiede la lettura di un intero file di dimensioni variabili. La mia domanda, qual è il numero ottimale di byte da leggere da un file e trasferirlo a un coprocessore (dispositivo CUDA)?Trasferimento efficiente di file di grandi dimensioni (fino a 2 GB) alla GPU CUDA?

Questi file possono essere grandi come 2GiB, quindi la creazione di un buffer di quelle dimensioni non sembra l'idea migliore.

risposta

4

È possibile cudaMalloc un buffer della dimensione massima che è possibile sul dispositivo. Dopodiché, copia su blocchi di dati di input di queste dimensioni da host a dispositivo, elaborali, copia i risultati e continua.

// Your input data on host 
int hostBufNum = 5600000; 
int* hostBuf = ...; 

// Assume this is largest device buffer you can allocate 
int devBufNum = 1000000; 
int* devBuf; 

cudaMalloc(&devBuf, sizeof(int) * devBufNum); 

int* hostChunk = hostBuf; 
int hostLeft = hostBufNum; 
int chunkNum = (hostLeft < devBufNum) ? hostLeft : devBufNum; 

do 
{ 
    cudaMemcpy(devBuf, hostChunk, chunkNum * sizeof(int) , cudaMemcpyHostToDevice); 
    doSomethingKernel<<< >>>(devBuf, chunkNum); 

    hostChunk = hostChunk + chunkNum; 
    hostLeft = hostBufNum - (hostChunk - hostBuf); 
} while(hostLeft > 0);  
+0

Quella parte che stavo già pianificando, ma quale dimensione dovrebbero essere i blocchi dei dati di input? – sj755

+0

La dimensione dell'array più grande che è possibile allocare sul dispositivo. –

+5

Puoi prendere in considerazione l'uso di memcopie asincrone di pezzi più piccoli di quelli che si trovano nella memoria (al massimo metà) e l'elaborazione del chunk 'k' in parallelo con il trasferimento del chunk' k-1' all'host e il trasferimento del chunk 'k + 1' da l'host al dispositivo. La sovrapposizione bidirezionale richiede una GPU Tesla, ma è possibile sovrapporre una direzione anche su GeForce. – harrism

0

Se è possibile dividere la funzione in modo da poter lavorare su pezzi sulla carta, si dovrebbe guardare in utilizzando flussi (cudaStream_t).

Se si pianificano carichi ed esecuzioni del kernel in più flussi, è possibile avere un flusso di dati di caricamento mentre un altro esegue un kernel sulla scheda, nascondendo in tal modo parte del tempo di trasferimento dei dati nell'esecuzione di un kernel.

È necessario dichiarare un buffer di qualunque sia la dimensione del blocco in termini di ore, tuttavia molti flussi dichiarati (fino a 16, per capacità di calcolo 1.x per quanto ne so).