CMake CUDA:与 cublas 的静态链接

问题描述 投票:0回答:1

我想编译CUDALibrarySamples。 cuFFT 使用 cmake,我想用静态版本的 cufft lib (

1d_c2c
) 编译和链接
-lcufft_static
应用程序。使用 Makefiles 很简单我在
中添加了
-lcufft_static

nvcc -x cu $(FLAGS) $(INC) 1d_c2c_example.cpp -o 1d_c2c_example $(LIBS)

但是,我不确定如何使用 cmake 做同样的事情。我注意到 cmake 有静态标志:

CUDA_cublasLt_static_LIBRARY
CUDA_cufft_static_LIBRARY
等。所以我的问题是如何启用它们? 提前谢谢你!

我试过了

target_link_libraries(${ROUTINE}_example PRIVATE ${CUDA_cufft_static_LIBRARY})

但是好像不行。

根据@paleonix 的建议,我做了以下事情:

target_link_libraries(${ROUTINE}_example PRIVATE CUDA::cufft_static CUDA::cudart). 

但是我收到以下错误:

/usr/bin/ld: /opt/cuda/lib64/libcufft_static.a(cbdouble_32bit_prime_callback_RT_SM35_plus.o): in function __sti____cudaRegisterAll()': cbdouble_32bit_prime_callback_RT_SM35_plus.compute_86.cudafe1.cpp:(.text.startup+0x1d): undefined reference to __cudaRegisterLinkedBinary_61_cbdouble_32bit_prime_callback_RT_SM35_plus_compute_86_cpp1_ii_dc5d5345

我正在尝试为 CUDA 库示例构建以下示例:

1d_c2c_example.cpp

#include <complex>
#include <iostream>
#include <random>
#include <vector>    
#include <cuda_runtime.h>
#include <cufftXt.h>
#include "cufft_utils.h"
int main(int argc, char *argv[]) {
    cufftHandle plan;
    cudaStream_t stream = NULL;
    
    int n = 8;
    int batch_size = 2;
    int fft_size = batch_size * n;
    
    using scalar_type = float;
    using data_type = std::complex<scalar_type>;
    std::vector<data_type> data(fft_size);
    for (int i = 0; i < fft_size; i++) {
        data[i] = data_type(i, -i);
    }
    
    std::printf("Input array:\n");
    for (auto &i : data) {
        std::printf("%f + %fj\n", i.real(), i.imag());
    }
    std::printf("=====\n");
    
    cufftComplex *d_data = nullptr;
    
    CUFFT_CALL(cufftCreate(&plan));
    CUFFT_CALL(cufftPlan1d(&plan, data.size(), CUFFT_C2C, batch_size));
    
    CUDA_RT_CALL(cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking));
    CUFFT_CALL(cufftSetStream(plan, stream));
    
    // Create device data arrays
    CUDA_RT_CALL(cudaMalloc(reinterpret_cast<void **>(&d_data), sizeof(data_type) * data.size()));
    CUDA_RT_CALL(cudaMemcpyAsync(d_data, data.data(), sizeof(data_type) * data.size(), cudaMemcpyHostToDevice, stream));
    
    CUFFT_CALL(cufftExecC2C(plan, d_data, d_data, CUFFT_FORWARD));
    CUFFT_CALL(cufftExecC2C(plan, d_data, d_data, CUFFT_INVERSE));
    
    CUDA_RT_CALL(cudaMemcpyAsync(data.data(), d_data, sizeof(data_type) * data.size(), cudaMemcpyDeviceToHost, stream));
    
    CUDA_RT_CALL(cudaStreamSynchronize(stream));
    
    /* free resources */
    CUDA_RT_CALL(cudaFree(d_data))
    CUFFT_CALL(cufftDestroy(plan));
    CUDA_RT_CALL(cudaStreamDestroy(stream));
    CUDA_RT_CALL(cudaDeviceReset());
    return EXIT_SUCCESS;
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.18)

set(ROUTINE 1d_c2c)

project(
  "${ROUTINE}_example"
  DESCRIPTION "GPU-Accelerated Fast Fourier Transforms"
  HOMEPAGE_URL "https://docs.nvidia.com/cuda/cufft/index.html"
  LANGUAGES CXX CUDA)

set(CMAKE_CUDA_ARCHITECTURES 80)
find_package(CUDAToolkit REQUIRED)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if("${CMAKE_BUILD_TYPE}" STREQUAL "")
  set(CMAKE_BUILD_TYPE Release)
endif()

set(CMAKE_CUDA_ARCHITECTURES 80)
#if(CMAKE_CUDA_ARCHITECTURES LESS 60)
    #set(CMAKE_CUDA_ARCHITECTURES 60 70 75 80 86)
    #endif()
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CUFFT_LIBRARIES ${CUDA_cufft_LIBRARY} ${CUDA_culibos_LIBRARY} ${CUDA_cudart_LIBRARY})


add_executable(${ROUTINE}_example)

target_include_directories(${ROUTINE}_example
                           PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} 
                           ${CMAKE_SOURCE_DIR}/../utils)

target_sources(${ROUTINE}_example
               PRIVATE ${PROJECT_SOURCE_DIR}/${ROUTINE}_example.cpp)

set(CMAKE_CUDA_ARCHITECTURES 80)
#target_link_libraries(${ROUTINE}_example PRIVATE ${CUDA_cufft_static_LIBRARY} CUDA::cufft CUDA::cudart)
target_link_libraries(${ROUTINE}_example PRIVATE CUDA::cufft_static CUDA::cudart)

当我删除

find_package(CUDAToolkit REQUIRED)

cmake 显示以下错误:

CMake Error at CMakeLists.txt:82 (target_link_libraries):
   Target "1d_c2c_example" links to:

     CUDA::cufft_static

   but the target was not found.
cmake compilation cuda static-linking cufft
1个回答
1
投票

使用

CUDA::cufft_static
后仍然存在链接器问题的主要原因是静态 cuFFT 需要启用可重定位设备代码。这是通过
CUDA_SEPARABLE_COMPILATION
属性在 CMake 中完成的。

我会收回我的声明,即一个人不应该同时使用

CUDA
语言和
find_package(CUDAToolkit REQUIRED)
。虽然
cufft_static
目标在仅使用语言时可用,但它不会自动链接
culibos
。所以更优雅的解决方案似乎是使用包中的
CUDA::cufft_static

我从链接的存储库中获取了

cufft_utils.h
并将其放入
${PROJECT_SOURCE_DIR}/utils
。如果您的项目结构不同,您将不得不调整
target_include_directories
命令。

Setting

CMAKE_
variables is bad style.要使其中一些起作用,您必须在
project
命令之前设置它们。但是例如CUDA 体系结构和构建类型应在第一次配置期间通过命令行参数设置为
cmake
或使用
ccmake
获得漂亮的控制台 ui.

cmake_minimum_required(VERSION 3.18)

set(ROUTINE 1d_c2c)

project(
  "${ROUTINE}_example"
  DESCRIPTION "GPU-Accelerated Fast Fourier Transforms"
  HOMEPAGE_URL "https://docs.nvidia.com/cuda/cufft/index.html"
  LANGUAGES CXX CUDA)

find_package(CUDAToolkit REQUIRED)

add_executable(${ROUTINE}_example)

set_target_properties(${ROUTINE}_example
  PROPERTIES
    CUDA_SEPARABLE_COMPILATION ON
    RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

target_compile_features(${ROUTINE}_example
  PRIVATE cuda_std_11)

target_sources(${ROUTINE}_example
  PRIVATE ${PROJECT_SOURCE_DIR}/${ROUTINE}_example.cu)

target_include_directories(${ROUTINE}_example
  PRIVATE ${PROJECT_SOURCE_DIR}/utils)

target_link_libraries(${ROUTINE}_example PRIVATE
  PRIVATE CUDA::cufft_static)

如您所见,我给源文件打了

.cu
。让它为
.cpp
文件工作似乎有点复杂。阅读该问题的一个很好的起点是 cuFFT 文档的本章。虽然可以通过使用
find_package(Threads REQUIRED)
然后将
${CMAKE_DL_LIBS}
Threads::Threads
添加到
target_link_libraries
命令来消除大多数链接器错误,但我无法使可重定位设备代码工作,因为我无法使用 CMake
nvcc
用于链接。我尝试在
LINKER_LANGUAGE CUDA
中设置
set_target_properties
这在理论上应该有效,但实际上 CMake 一直使用
g++
进行链接(用
make VERBOSE=1
可见)。这可能是 CMake 中的错误。

© www.soinside.com 2019 - 2024. All rights reserved.