2012-07-26 15 views
9

No es un secreto que en CUDA 4.x la primera llamada a cudaMalloc puede ser ridículamente lenta (lo que se informó varias veces), aparentemente un error en los controladores CUDA.La vinculación con bibliotecas CUDA de terceros ralentiza cudaMalloc

Recientemente, he notado un comportamiento extraño: el tiempo de ejecución de cudaMalloc depende directamente de la cantidad de bibliotecas CUDA 3 ª parte he vinculado a mi programa (nótese que no utilizan estos bibliotecas, simplemente enlazar mi programa con ellos)

me corrieron algunas pruebas con el siguiente programa:

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

los resultados son los siguientes:

  • Vinculado con: -lcudart -lnpp -lcufft -lcublas -lcusparse -lcurand Duración: 5,852449

  • Vinculado con: 1,425120

  • Vinculado con: -lcudart -lnpp -lcufft -lcublas tiempo de ejecución: -lcudart -lnpp -lcufft tiempo de ejecución: 0.905424

  • enlazadas con: -lcudart tiempo de ejecución: 0,394558

Según 'gdb', el tiempo ind eed va a mi cudaMalloc, por lo que no es causado por alguna rutina de inicialización de la biblioteca ..

Me pregunto si alguien tiene una explicación plausible para esto?

Respuesta

11

En su ejemplo, la llamada cudaMalloc inicia el establecimiento de contexto vago en la GPU. Cuando se incluyen bibliotecas de API en tiempo de ejecución, sus cargas binarias deben inspeccionarse y los símbolos y objetos de duende de la GPU que contienen se fusionaron en el contexto. Cuantas más bibliotecas haya, más tiempo puede esperar que tarde el proceso. Además, si hay una discrepancia de arquitectura en cualquiera de los cubins y tiene una GPU compatible hacia atrás, también puede desencadenar la recompilación del controlador del código del dispositivo para la GPU de destino. En un caso muy extremo, he visto que una aplicación antigua vinculada con una versión anterior de CUBLAS toma 10 segundos para cargar e inicializar cuando se ejecuta en una GPU de Fermi.

Puede forzar explícitamente contexto establecimiento vago mediante la emisión de una llamada cudaFree así:

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; 
} 

Si perfil o instrumento esta versión con temporizadores que debe encontrar que la primera cudaFree llamada consume la mayor parte del tiempo de ejecución y el cudaMalloc llamada se vuelve casi gratis.

+0

gracias @talomnies, de hecho insertando cudaFree al principio toma todo el tiempo de ejecución. Probé este programa originalmente en una tarjeta gráfica GT650M (Kepler core) mientras que en Fermi GPU GTX580 tarda aún más - aproximadamente 7 segundos ... todavía NVIDIA podría hacer algo para optimizar su gestión de contexto: 7 segundos con la carga de trabajo completa de la CPU parece ser demasiado –

+0

@asm: pruebe CUDA 5 y vea lo que hace. Ahora hay un enlazador de código de dispositivo adecuado en la cadena de herramientas, por lo que algunos de los gastos generales en tiempo de ejecución podrían cambiarse para compilar y vincular el tiempo (o al menos simplificarse un poco). Además, si encuentra que esto responde su pregunta, puede ser tan amable de aceptarlo para que su pregunta se marque como respondida. – talonmies

+0

Tenga en cuenta que en CUDA 4.0, parte de la razón por la que la inicialización de CUDA lleva tanto tiempo se debe a que el controlador está realizando asignaciones masivas de memoria virtual para el direccionamiento virtual unificado. – ArchaeaSoftware

Cuestiones relacionadas