2012-03-16 17 views
6

Estoy trabajando en un programa acelerado de GPU que requiere la lectura de un archivo completo de tamaño variable. Mi pregunta, ¿cuál es el número óptimo de bytes para leer desde un archivo y transferirlo a un coprocesador (dispositivo CUDA)?¿Transfiere eficientemente archivos grandes (hasta 2GB) a la GPU CUDA?

Estos archivos pueden ser tan grandes como 2GiB, por lo que crear un búfer de ese tamaño no parece ser la mejor idea.

Respuesta

4

Puede cudaMalloc un búfer del tamaño máximo que pueda en su dispositivo. Después de esto, copie los fragmentos de sus datos de entrada de este tamaño de host a dispositivo, trátelos, copie los resultados y continúe.

// 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

Esa parte que ya estaba planeando, pero ¿qué tamaño deberían tener los fragmentos de datos de entrada? – sj755

+0

El tamaño de la matriz más grande que puede asignar en el dispositivo. –

+5

Podría considerar usar memcopias asincrónicas de trozos algo más pequeños de lo que cabe en la memoria (como máximo a la mitad) y procesar el trozo 'k' en paralelo con la transferencia del trozo' k-1' al host y transferir el trozo 'k + 1' de el anfitrión del dispositivo. La superposición bidireccional requiere una GPU Tesla, pero puede superponerse en una dirección incluso en GeForce. – harrism

0

Si usted puede dividir su función para que pueda trabajar en trozos en la tarjeta, usted debe buscar en arroyos (utilizando cudaStream_t).

Si programa cargas y ejecuciones de kernel en varias secuencias, puede hacer que una secuencia cargue datos mientras otra ejecuta un kernel en la tarjeta, ocultando parte del tiempo de transferencia de sus datos en la ejecución de un kernel.

Debe declarar un búfer de lo que sea que el tamaño de su porción sea veces sin importar cuántas secuencias declare (hasta 16, para la capacidad de cálculo 1.x hasta donde yo sé).

Cuestiones relacionadas