2012-02-20 23 views
8

Estoy intentando modificar un programa GPL escrito en C. Mi objetivo es reemplazar un método con una implementación CUDA, lo que significa que necesito compilar con nvcc en lugar de gcc. Necesito ayuda para construir el proyecto, no para implementarlo (no necesita saber nada sobre CUDA C para ayudar, no creo).Construyendo el programa GPL C con el módulo CUDA

Esta es la primera vez que intento cambiar un proyecto C de complejidad moderada que implica una .configure y Makefile. Honestamente, esta es la primera vez que hago cualquier cosa en C en mucho tiempo, incluyendo cualquier cosa relacionada con gcc o g ++, así que estoy bastante perdido.

No estoy muy interesado en aprender a configurar y Makefiles: esto es más un experimento. Me gustaría ver si la implementación del proyecto va bien antes de dedicar tiempo a crear un script de compilación adecuado. (No está dispuesto a aprender si es necesario, solo intenta dar una idea del alcance).

Dicho esto, ¿cuáles son mis opciones para construir este proyecto? Tengo una gran cantidad de preguntas ...

  • He intentado añadir "CC = NVCC" al archivo configure.in después AC_PROG_CC. Esto pareció funcionar: salió de la ejecución de configure y make mostró nvcc como el compilador. Sin embargo, make no compiló el archivo fuente con el kernel CUDA, sin reconocer la sintaxis específica de CUDA. No sé por qué, esperaba que esto solo funcionara.

  • ¿Es posible compilar un archivo fuente con nvcc, y luego incluirlo en el paso de vinculación en el proceso de creación para el programa principal? ¿Si es así, cómo? (Esta pregunta podría no tener sentido - estoy realmente oxidado al respecto)

  • ¿Cuál es la forma correcta de hacerlo?

  • ¿Hay alguna manera rápida y sucia que podría utilizar para realizar pruebas?

  • ¿Existe alguna herramienta secreta que todos utilicen para configurar y comprender estos archivos de configuración y Makefiles? Esto es incluso peor que los scripts Ant de Apache que estoy acostumbrado (Sí, estoy fuera de mi reino)

+2

Lo que quizás se haya perdido es extensiones de archivo. nvcc utiliza extensiones de archivos para determinar qué contiene el código del dispositivo y qué no; cualquier código de dispositivo que contenga archivos debe tener una extensión '.cu' para compilarse correctamente. – talonmies

+0

Simplemente curioso, ¿qué estás haciendo en la función CUDA? – arrayfire

+0

Buen punto acerca de los archivos .cu. Voy a tratar de cambiar el nombre de algunos de los archivos de origen. – emulcahy

Respuesta

14

No es necesario compilar todo con NVCC. Supongo que puede compilar su código CUDA con NVCC y dejar todo lo demás (excepto los enlaces) es correcto. Este es el enfoque que usaría para comenzar.

  1. Añadir un 1 nueva cabecera (por ejemplo myCudaImplementation.h) y 1 nuevo archivo de fuente (con .cu extensión, por ejemplo myCudaImplementation.cu). El archivo de origen contiene la implementación de kernel y una función de contenedor C (host) que invoca al kernel con la configuración de ejecución adecuada (también conocida como <<<>>>) y argumentos. El archivo de encabezado contiene el prototipo de la función C wrapper. Vamos a llamar a esa función de contenedor runCudaImplementation()

  2. También proporcionaría otra función de host C en el archivo de origen (con prototipo en el encabezado) que consulta y configura los dispositivos GPU presentes y devuelve verdadero si es exitoso, falso si no. Llamemos a esta función configureCudaDevice().

  3. Ahora en su código C original, donde normalmente llamaría a la implementación de su CPU, puede hacerlo.

    // must include your new header 
    #include "myCudaImplementation.h" 
    
    // at app initialization 
    // store this variable somewhere you can access it later 
    bool deviceConfigured = configureCudaDevice;   
    ...        
    // then later, at run time 
    if (deviceConfigured) 
        runCudaImplementation(); 
    else 
        runCpuImplementation(); // run the original code 
    
  4. Ahora, ya que pone todo su código CUDA en un nuevo archivo .cu, es suficiente para compilar ese archivo con NVCC. Todo lo demás permanece igual, excepto que tiene que vincular en el archivo objeto que produce nvcc. p.ej.

    nvcc -c -o myCudaImplementation.o myCudaImplementation.cu <other necessary arguments> 
    

A continuación, añadir myCudaImplementation.o a su línea de enlace (algo así como :) g ++ -o myApp myCudaImplementation.o

Ahora, si usted tiene una aplicación compleja para trabajar con que utiliza configure y tiene un archivo MAKE complejo ya, puede estar más involucrado que el anterior, pero este es el enfoque general. En pocas palabras, no desea compilar todos sus archivos fuente con nvcc, solo los .cu. Usa tu compilador de host para todo lo demás.

No soy experto en configurar, así que realmente no puedo ayudar. Puede ejecutar configure para generar un archivo MAKE y luego editar ese archivo MAKE; no será una solución general, pero lo ayudará a comenzar.

+0

Genial, gracias por tomarse el tiempo para explicar eso. Puedo manejar ese enfoque. – emulcahy

+0

Lo tengo trabajando. Un paso adicional que otros pueden necesitar es agregar extern "C" {} alrededor del método de envoltura. Sin embargo, esto es probablemente obvio para vincular a los veteranos. – emulcahy

+1

No debería tener que usar extern "C" a menos que solo tenga un enlace C (por ejemplo, llamarlo desde un archivo .c). – harrism