Я хочу скомпилировать CUDALibrarySamples. cuFFT использует cmake, и я хочу скомпилировать и связать приложение 1d_c2c со статической версией cufft lib (-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:
#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;
}
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.
Вы пытаетесь использовать устаревшую функциональность из старого FindCUDA. Я бы рекомендовал не использовать версию CMake, которая поддерживает более новый API, 3.18 — хорошее начало.
Я удалю find_package и повторю попытку. Что касается .cu, я не думаю, что это проблема, потому что с Makefile он компилируется. Как вы думаете, есть проблема с .cu и cmake?
Я исправил свой ответ для работы с исходным файлом .cpp.





Основная причина, по которой у вас все еще были проблемы с компоновщиком после использования CUDA::cufft_static, заключалась в том, что для статического cuFFT требуется включенный код перемещаемого устройства. Хотя это делается в CMake с помощью свойства CUDA_SEPARABLE_COMPILATION для компиляции, нам это нужно для связывания, которое достигается с помощью свойства CUDA_RESOLVE_DEVICE_SYMBOLS.
Я откажусь от своего заявления о том, что нельзя использовать одновременно язык CUDA и find_package(CUDAToolkit REQUIRED). Хотя цель cufft_static доступна при использовании только языка, она не связывается автоматически с culibos. Таким образом, более элегантным решением является использование CUDA::cufft_static из пакета.
Архитектура CUDA и тип сборки должны быть установлены во время первой настройки либо с помощью аргументов командной строки cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CUDA_ARCHITECTURES=80, либо с помощью ccmake, чтобы получить приятный интерфейс консоли.
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_RESOLVE_DEVICE_SYMBOLS ON
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
target_compile_features(${ROUTINE}_example
PRIVATE cxx_std_11)
target_sources(${ROUTINE}_example
PRIVATE ${PROJECT_SOURCE_DIR}/${ROUTINE}_example.cpp)
target_include_directories(${ROUTINE}_example
PRIVATE ${CMAKE_SOURCE_DIR}/../utils)
target_link_libraries(${ROUTINE}_example PRIVATE
PRIVATE
CUDA::cufft_static
CUDA::cudart_static)
Спасибо @RobertJMaynard, который помог мне понять, как правильно сделать ссылку, не меняя исходный файл на .cu (т. е. использовать CUDA_RESOLVE_DEVICE_SYMBOLS и добавить CUDA::cudart_static) на CMake Discourse.
У меня такая же проблема с bazel и tensorflow. Что эквивалентно CUDA_RESOLVE_DEVICE_SYMBOLS в базеле?
Я не знаю Базеля. Пожалуйста, откройте новый вопрос. Погуглив проблему, этот образец bazel кажется, что он может помочь, то есть rdc = 1.
target_link_libraries(${ROUTINE}_example PRIVATE cufft_static)при использовании FindCUDAToolkit() вместо языка добавьтеCUDA::перед целевой библиотекой. См. связанные документы.