El plazo de configuración de mi cuda biblioteca está aumentando y así que pensé que de compilación independiente introducido en CUDA 5.0 me podría ayudar. Yo no podía entender cómo lograr compilación independiente con cmake. Miré en la NVCC documentación y a encontrar la forma de compilar el objeto de dispositivo (usando la opción de dc) y cómo vincularlos (usando la opción-dlink). Mis intentos para conseguir que se ejecuta con cmake fallado. Estoy usando cmake 2.8.10.2 y la cabeza del tronco de la FindCUDA.cmake. No podía sin embargo averiguar cómo especificar qué archivos deben ser compilados y cómo vincularlos en una biblioteca.
Especialmente la sintaxis de la function(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file_var cuda_target options object_files source_files)
está claro para mí porque no sé lo que el output_file_var y la cuda_target.
Aquí el que no trabaja resultados de mis intentos:

cuda_compile(DEVICEMANAGER_O devicemanager.cu OPTIONS -dc)
cuda_compile(BLUB_O blub.cu OPTIONS -dc)
CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS(TEST_O gpuacceleration
                                          ""  DEVICEMANGER_O BLUB_O)
set(LIB_TYPE SHARED)
#cuda_add_library(gpuacceleration ${LIB_TYPE} 
  #${gpuacc_SRCS} 
  #devicemanager.cu
  # blub.cu
  #DEVICEMANAGER_O
#  TEST_O
#)

¿Alguien sabe cómo compilar y enlazar un cuda biblioteca con cmake?
Gracias de antemano.

EDICIÓN:
Después de que un amigo consultado el desarrollador de la FindCUDA.cmake, un error que se resolvieron en el ejemplo proporcionado con FindCUDA.cmake (https://gforge.sci.utah.edu/gf/project/findcuda/scmsvn/?action=browse&path=%2Fcheckout%2Ftrunk%2FFindCuda.html).
Ahora soy capaz de construir el ejemplo.
En mi proyecto de que se puede construir la biblioteca como sea necesario con el siguiente (cmake 2.8.10 requerido):

set(LIB_TYPE SHARED)
set(CUDA_SEPARABLE_COMPILATION ON)
cuda_add_library(gpuacceleration ${LIB_TYPE} 
 blub.cu
 blab.cu
)

PERO:
No puedo enlace a esta librería. Cuando yo edificado el lib sin separar la compilación yo era capaz de enlace en contra de ella.
Ahora recibiendo el siguiente error:

 undefined reference to `__cudaRegisterLinkedBinary_53_tmpxft_00005ab4_00000000_6_blub_cpp1_ii_d07d5695'

para cada archivo con una función que se utiliza en la interfaz. Parece extraño ya que se construye sin ningún tipo de advertencia, etc.
Alguna idea de cómo conseguir este trabajo?

EDICIÓN:
Finalmente me di cuenta de cómo hacer esto. Ver a @DOCTORADO y mi respuesta para más detalles.

Esto es confirmado como un error en FindCUDA (véase mi respuesta a continuación).

OriginalEl autor soriak | 2012-12-03

4 Comentarios

  1. 3

    Por fin lo conseguí corriendo 😉

    Además de la respuesta de @DOCTORADO y mi comentario sobre lo que he modificado: set(BUILD_SHARED_LIBS OFF) en mi CMakeLists.txt desde librerías compartidas no son compatibles para la compilación independiente de acuerdo a la nvcc manualmente v5.0 página 40.

    Además de que el uso de la última rev (1223) desde el repositorio en lugar de rev 1221. Me puse en contacto con el desarrollador y se fija a algún problema de bloqueo de este.
    Esta revisión no establece el nvcc -arch=sm_xx bandera correctamente, así que he añadido manualmente para mi proyecto e informó que el desarrollador de FindCUDA.cmake. Así que esto puede ser corregido en el futuro.

    No se olvide de obtener cmake > 2.8.10 para que esto funcione.

    Espero que esto ayude a nadie sino a mí 😉

    Aquí está mi CMakeLists.txt:

    #Required for CUDA-Check
    cmake_minimum_required(VERSION 2.8.10)
    
    project(gpulib)
    
    set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake/cuda" ${CMAKE_MODULE_PATH})
    # ============================================
    # === Target
    # ============================================
    file(GLOB_RECURSE gpuacc_SRCS "*.cu")
    include_directories(.)
    
    # ---------------------------------------
    # Find Cuda
    find_package(CUDA REQUIRED)
    
    set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE ON)
    
    set(BUILD_SHARED_LIBS OFF)
    
    set(CUDA_SEPARABLE_COMPILATION ON)
    #list(APPEND CUDA_NVCC_FLAGS -arch=sm_20)
    
    set(LIB_NAME "gpuacceleration")
    cuda_add_library(${LIB_NAME}
      ${gpuacc_SRCS} 
      OPTIONS -DSTUFF="blah blah"
      RELEASE -DNDEBUG
      DEBUG -g -DDEBUG
    )
    
    set(PUBLIC_HEADERS "myheader1.h;myheader2.h")
    
    INSTALL(FILES ${PUBLIC_HEADERS} DESTINATION include)
    INSTALL(FILES "${CMAKE_BINARY_DIR}/src/lib${LIB_NAME}.a" DESTINATION lib)

    EDIT: esto no está funcionando!
    El problema es que no están definidos en referencias para todos los cuda funciones (por ejemplo. cudaMalloc) cuando la vinculación de la biblioteca generado durante la construcción de un ejecutable en el proyecto principal.

    Sigue trabajando en ello

    Has encontrado finalmente una solución para este problema?
    No hay solución, pero revise mi respuesta a continuación para obtener más información sobre el problema.

    OriginalEl autor soriak

  2. 3

    EDITAR (2016-03-15): Sí, se confirma como un error en FindCUDA: https://cmake.org/Bug/view.php?id=15157


    TL;DR: Esto parece ser un error en FindCUDA, lo que hace que los objetos sueltos información sobre definiciones externas antes de la final de vinculación.

    El problema es que, incluso si separables compilación está habilitada, una vinculación de paso todavía se realiza para todos los objetivos de forma individual antes de la final de vinculación.

    Por ejemplo, yo tengo module.cu con:

    #include "module.h"
    #include <cstdio>
    
    double arr[10] = {1,2,3,4,5,6,7,8,9,10};
    __constant__ double carr[10];
    
    void init_carr() {
      cudaMemcpyToSymbol(carr,arr,10*sizeof(double));
    }
    
    __global__ void pkernel() {
      printf("(pkernel) carr[%d]=%g\n",threadIdx.x,carr[threadIdx.x]);
    }
    
    void print_carr() {
      printf("in print_carr\n");
      pkernel<<<1,10>>>();
    }

    y module.h con:

    extern __constant__ double carr[10];
    extern double arr[10];
    
    void print_carr();
    void init_carr();

    y finalmente main.cu con:

    #include "module.h"
    
    #include <cstdio>
    
    __global__ void kernel() {
      printf("(kernel) carr[%d]=%g\n",threadIdx.x,carr[threadIdx.x]);
    }
    
    
    int main(int argc, char *argv[]) {
      printf("arr: %g %g %g ..\n",arr[0],arr[1],arr[2]);
    
      kernel<<<1,10>>>();
      cudaDeviceSynchronize();
      print_carr();
      cudaDeviceSynchronize();
      init_carr();
      cudaDeviceSynchronize();
      kernel<<<1,10>>>();
      cudaDeviceSynchronize();
      print_carr();
      cudaDeviceSynchronize();
    
      return 0;
    }

    Esto, entonces funciona bien con el siguiente Makefile:

    NVCC=nvcc
    NVCCFLAGS=-arch=sm_20
    LIB=libmodule.a
    OBJS=module.o main.o
    PROG=extern
    
    $(PROG): main.o libmodule.a
        $(NVCC) $(NVCCFLAGS) -o [email protected] $^
    
    %.o: %.cu
        $(NVCC) $(NVCCFLAGS) -dc -c -o [email protected] $^
    
    $(LIB): module.o
        ar cr [email protected] $^
    
    clean:
        $(RM) $(PROG) $(OBJS) $(LIB)

    Pero luego me pruebe a utilizar el siguiente CMakeLists.txt:

    CMAKE_MINIMUM_REQUIRED(VERSION 2.8.8)
    
    PROJECT(extern)
    
    FIND_PACKAGE(CUDA REQUIRED)
    SET(CUDA_SEPARABLE_COMPILATION ON)
    
    SITE_NAME(HOSTNAME)
    
    SET(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} -arch=sm_20)
    
    cuda_add_library(module module.cu)
    
    CUDA_ADD_EXECUTABLE(extern main.cu)
    TARGET_LINK_LIBRARIES(extern module)

    Cuando, a continuación, compilar, ¿qué sucede entonces es que la siguiente:

    $ cmake ..
    -- The C compiler identification is GNU 4.9.2
    ...
    $ make VERBOSE=1
    ...
    [ 25%] Building NVCC (Device) object CMakeFiles/module.dir//./module_generated_module.cu.o
    ...
    -- Generating <...>/build/CMakeFiles/module.dir//./module_generated_module.cu.o
    /usr/local/cuda/bin/nvcc <...>/module.cu -dc -o <...>/build/CMakeFiles/module.dir//./module_generated_module.cu.o -ccbin /usr/bin/cc -m64 -Xcompiler ,\"-g\" -arch=sm_20 -DNVCC -I/usr/local/cuda/include
    [ 50%] Building NVCC intermediate link file CMakeFiles/module.dir/./module_intermediate_link.o
    /usr/local/cuda/bin/nvcc -arch=sm_20 -m64 -ccbin "/usr/bin/cc" -dlink <...>/build/CMakeFiles/module.dir//./module_generated_module.cu.o -o <...>/build/CMakeFiles/module.dir/./module_intermediate_link.o
    ...
    /usr/bin/ar cr libmodule.a  CMakeFiles/module.dir/./module_generated_module.cu.o CMakeFiles/module.dir/./module_intermediate_link.o
    /usr/bin/ranlib libmodule.a
    ...
    [ 50%] Built target module
    [ 75%] Building NVCC (Device) object CMakeFiles/extern.dir//./extern_generated_main.cu.o
    ...
    -- Generating <...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o
    /usr/local/cuda/bin/nvcc <...>/main.cu -dc -o <...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o -ccbin /usr/bin/cc -m64 -Xcompiler ,\"-g\" -arch=sm_20 -DNVCC -I/usr/local/cuda/include -I/usr/local/cuda/include
    ...
    [100%] Building NVCC intermediate link file CMakeFiles/extern.dir/./extern_intermediate_link.o
    /usr/local/cuda/bin/nvcc -arch=sm_20 -m64 -ccbin "/usr/bin/cc" -dlink <...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o -o <...>/build/CMakeFiles/extern.dir/./extern_intermediate_link.o
    nvlink error   : Undefined reference to 'carr' in '<...>/build/CMakeFiles/extern.dir//./extern_generated_main.cu.o'

    Claramente, el problema son los nvcc -dlink obj.o -o obj_intermediate_link.o líneas. Entonces, supongo, la información sobre definiciones externas se pierden. Entonces, la pregunta es, es posible hacer CMake/FindCUDA no hacer este extra vinculación paso?

    Lo contrario, yo diría que esto es un error. ¿Estás de acuerdo? Yo puedo presentar un informe de error con CMake.

    OriginalEl autor kalj

  3. 2

    Probado con nvcc versión:

    nvcc: NVIDIA (R) Cuda compiler driver Copyright (c) 2005-2012 NVIDIA
    Corporation Built on Fri_Sep_21_17:28:58_PDT_2012 Cuda compilation
    tools, release 5.0, V0.2.1221

    y svn revision:

    URL: https://gforge.sci.utah.edu/svn/findcuda/trunk
    Repository Root: https://gforge.sci.utah.edu/svn/findcuda
    Repository UUID: 81322f20-870f-0410-845c-a4cd4664c908
    Revision: 1221
    Node Kind: directory
    Schedule: normal
    Last Changed Rev: 1221
    Last Changed Date: 2013-01-28 22:31:07 +0100 (Mon, 28 Jan 2013)

    En este ejemplo incluye las siguientes clases:

    • lib.h /lib.cu
    • kernel.h /kernel.cu

    kernel.cu contiene un simple kernel CUDA y una clase con un método público para llamar a la CUDA kernel. La clase lib contiene una instancia de la clase kernel y un método de llamar al método público de la clase kernel.

    Siguientes CMakeLists.txt funciona con esta configuración:

    cmake_minimum_required(VERSION 2.6.2)
    project(Cuda-project)
    set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/CMake/cuda" ${CMAKE_MODULE_PATH})
    find_package(CUDA QUIET REQUIRED)
    set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF)
    set(BUILD_SHARED_LIBS ON)
    list(APPEND CUDA_NVCC_FLAGS -DBLAH="he he" -DTEST1="this is a test")
    CUDA_ADD_LIBRARY(test_lib
    kernel.cu
    lib.cu
    # SHARED
    # STATIC
    OPTIONS -DSTUFF="blah blah"
    RELEASE --use_fast_math -DNDEBUG
    DEBUG -g -DDEBUG
    )
    INSTALL(FILES lib.h kernel.h
    DESTINATION include)
    INSTALL(FILES "${CMAKE_BINARY_DIR}/libtest_lib.so" 
    DESTINATION lib)
    la siguiente falta: set(CUDA_SEPARATE_COMPILATION). Además de eso, no he sido capaz de enlazar la librería generada. Hay una nueva versión de findcuda en el svn que voy a probar pronto.
    Por fin lo conseguí corriendo 😉 Además De la respuesta de @DOCTORADO y mi comentario anterior puse ‘BUILD_SHARED_LIBS OFF’ desde librerías compartidas no son compatibles para la compilación independiente de acuerdo a la nvcc manualmente v5.0 página 40.

    OriginalEl autor PHD

  4. 0

    No podía hacer que funciona utilizando el CUDA_ADD_EXECUTABLE así que he creado una función que realiza una costumbre de destino para hacerlo.

    function(add_cuda_exe_lib name files libraries is_lib)
    set (obj_list)
    foreach(file ${files})
    add_custom_command(
    OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${file}.o
    DEPENDS ${file} 
    COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --blue "Building NVCC Device object ${CMAKE_CURRENT_SOURCE_DIR}/${file}"
    COMMAND ${CUDA_NVCC_EXECUTABLE} ${CUDA_NVCC_FLAGS} -dc "${CMAKE_CURRENT_SOURCE_DIR}/${file}" -o "${CMAKE_CURRENT_BINARY_DIR}/${file}.o"
    COMMENT "Building ${CMAKE_CURRENT_SOURCE_DIR}/${file}"
    VERBATIM
    )
    LIST(APPEND obj_list ${CMAKE_CURRENT_BINARY_DIR}/${file}.o)
    endforeach()
    set (lib_list)
    LIST(APPEND lib_list "-lcudadevrt")
    foreach(library_name ${libraries})
    LIST(APPEND lib_list "-l${library_name}")
    endforeach()
    set (flags ${CUDA_NVCC_FLAGS})
    if (is_lib)
    LIST(APPEND flags "-dlink")
    set (obj_name "${CMAKE_CURRENT_BINARY_DIR}/${name}.so")
    else()
    set (obj_name "${CMAKE_CURRENT_BINARY_DIR}/${name}")
    endif()
    add_custom_target(${name} ALL 
    COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --red "Linking CXX executable ${name}"
    COMMAND ${CUDA_NVCC_EXECUTABLE} ${flags} ${obj_list} ${lib_list} -o ${obj_name}
    DEPENDS ${obj_list}
    COMMENT "Linking ${name}"
    )
    endfunction()
    function(add_cuda_exe name files libraries)
    add_cuda_exe_lib(${name} "${files}" "${libraries}" OFF)
    endfunction()
    function(add_cuda_lib name files libraries)
    add_cuda_exe_lib(${name} "${files}" "${libraries}" ON)
    endfunction()

    Ahora, para generar una lib, sólo tiene que utilizar:

    add_cuda_lib(testar "devicemanager.cu;blub.cu" "")

    O generar un archivo ejecutable:

    add_cuda_exe(testar "devicemanager.cu;blub.cu" "")

    El último parámetro es una lista de librerías para ser conectada.

    Espero te sirva de ayuda.

    OriginalEl autor Rodolfo

Dejar respuesta

Please enter your comment!
Please enter your name here