11

私の cuda ライブラリのビルド時間が増えているので、CUDA 5.0 で導入された個別のコンパイルが役立つのではないかと考えました。cmake で個別にコンパイルする方法がわかりませんでした。NVCC のドキュメントを調べて、デバイス オブジェクトをコンパイルする方法 (-dc オプションを使用) とそれらをリンクする方法 (-dlink を使用) を見つけました。cmake を使用して実行しようとして失敗しました。私はcmake 2.8.10.2とFindCUDA.cmakeのトランクの頭を使用しています。ただし、コンパイルする必要があるファイルを指定する方法と、それらをライブラリにリンクする方法を見つけることができませんでした。特に、とfunction(CUDA_LINK_SEPARABLE_COMPILATION_OBJECTS output_file_var cuda_target options object_files source_files) が何であるかがわからないため、 の構文はわかりません。ここに私の試みのうまくいかない結果があります:output_file_varcuda_target

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
#)

cmakeを使用してcudaライブラリをコンパイルおよびリンクする方法を知っている人はいますか? 前もって感謝します。

編集: 友人が FindCUDA.cmake の開発者に相談した後、FindCUDA.cmake で提供される例でバグが修正されました ( https://gforge.sci.utah.edu/gf/project/findcuda/scmsvn/?action=ブラウズ&パス=%2Fチェックアウト%2Ftrunk%2FFindCuda.html)。これで、例をビルドできます。私のプロジェクトでは、必要に応じて以下を使用してライブラリを構築できます (cmake 2.8.10 が必要です)。

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

BUT: このライブラリに対してリンクできません。個別にコンパイルせずにライブラリをビルドすると、リンクできました。次のエラーが表示されます。

 undefined reference to `__cudaRegisterLinkedBinary_53_tmpxft_00005ab4_00000000_6_blub_cpp1_ii_d07d5695'

インターフェイスで使用される関数を含むすべてのファイルに対して。警告などなしにビルドされるため、奇妙に思えます。これを機能させる方法はありますか?

編集: 私はついにこれを行う方法を見つけました。詳細については、@PHD と私の回答を参照してください。

4

4 に答える 4

5

私はついにそれを実行しました;)

@PHDの回答とそれに対する私のコメントに加えて、私は変更set(BUILD_SHARED_LIBS OFF)しました。CMakeLists.txt共有ライブラリは、nvcc手動v5.0ページ40による個別のコンパイルではサポートされていないためです。

それに加えて、rev 1221の代わりにリポジトリからの最新のrev(1223)を使用します。私は開発者に連絡し、彼はこれをブロックするいくつかの問題を修正しました。このリビジョンではフラグが正しく設定されていないnvcc -arch=sm_xxため、プロジェクトに手動で追加し、FindCUDA.cmakeの開発者に通知しました。したがって、これは将来修正される可能性があります。

これが機能するためには、cmake>2.8.10を取得することを忘れないでください。

これが私以外の誰かに役立つことを願っています;)

これが私の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)

編集:これは機能していません!問題は、メインプロジェクトで実行可能ファイルをビルドするときに、生成されたライブラリをリンクするときに、すべてのcuda関数(cudaMallocなど)への未定義の参照があることです。

まだそれに取り組んでいます

于 2013-02-02T09:52:54.793 に答える
3

編集 (2016-03-15): はい、FindCUDA のバグとして確認されています: https://cmake.org/Bug/view.php?id=15157


TL;DR: これは FindCUDA のバグのようで、最終的なリンクの前にオブジェクトが外部定義に関する情報を失います。

問題は、分離可能なコンパイルが有効になっている場合でも、最終的なリンクの前にすべてのターゲットに対してリンク手順が個別に実行されることです。

たとえば、私は持ってmodule.cuいます:

#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>>>();
}

そしてmodule.h

extern __constant__ double carr[10];
extern double arr[10];

void print_carr();
void init_carr();

そして最後main.cuに:

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

これは、次の場合に正常に機能します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 $@ $^

%.o: %.cu
    $(NVCC) $(NVCCFLAGS) -dc -c -o $@ $^

$(LIB): module.o
    ar cr $@ $^

clean:
    $(RM) $(PROG) $(OBJS) $(LIB)

しかし、私は以下を使用しようとします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)

次にコンパイルすると、次のことが起こります。

$ 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'

明らかに、問題はnvcc -dlink obj.o -o obj_intermediate_link.o行です。次に、外部定義に関する情報が失われると思います。それで、問題は、CMake/FindCUDA がこの追加のリンク手順を実行しないようにすることは可能ですか?

そうでなければ、これはバグだと主張します。同意しますか?CMake でバグ レポートを提出できます。

于 2015-10-20T09:36:19.863 に答える
2

nvcc バージョンでテストしました:

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

およびsvnリビジョン:

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)

この例には、次のクラスが含まれています。

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

kernel.cuシンプルな CUDA カーネルと、CUDA カーネルを呼び出す public メソッドを持つクラスが含まれています。クラス lib には、クラス カーネルのインスタンスと、クラス カーネルの public メソッドを呼び出すメソッドが含まれています。

以下CMakeLists.txtは、この構成で機能します。

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)
于 2013-01-30T11:12:23.567 に答える