"неизвестная ошибка" в первом cudaMalloc, если в ядре присутствует CUBLAS

У меня есть следующие минимальные .cu файл

#include <cuda_runtime_api.h>
#include <cublas_v2.h>
#include <cstdio>

__global__ void test()
{
    cublasHandle_t handle = nullptr;
    cublasCreate(&handle);
}

int main(int, char**)
{
    void * data = nullptr;
    auto err = cudaMalloc(&data, 256);
    printf("%s\n", cudaGetErrorString(err));
    return 0;
}

Как видите, test ядро даже не вызывается, однако cudaMalloc возвращается 30 (неизвестная ошибка). Файл компилируется с раздельной компиляцией (требуется для динамического параллелизма) и возможностью вычислений 5.2 (также пробовал 3.5 и 5.0, которые ничего не изменили). Удаление звонка cublasCreate причины cudaMalloc возвращать 0 (Нет ошибок).

Что может быть причиной? И как я могу это исправить? Мне нужно вызывать CUBLAS из ядра, используя динамический параллелизм, который теоретически поддерживается, поэтому "просто удалить вызов" не вариант.

Вот соответствующий CMakeLists.txt:

cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
project(CublasError)

find_package(CUDA REQUIRED)

set(CUDA_SEPARABLE_COMPILATION ON)
set(CUDA_NVCC_FLAGS --gpu-architecture=compute_52 -Xptxas=-v)
list(APPEND CUDA_NVCC_FLAGS_DEBUG -G -keep -O0)

cuda_add_executable(${PROJECT_NAME} main.cu)
cuda_add_cublas_to_target(${PROJECT_NAME})

# FindCUDA.cmake does not automatically add (or find) cudadevrt which is required when separable compilation is on
if(CUDA_SEPARABLE_COMPILATION)
    get_filename_component(CUDA_LIB_PATH ${CUDA_CUDART_LIBRARY} DIRECTORY)
    find_library(CUDA_cudadevrt_LIBRARY cudadevrt PATHS ${CUDA_LIB_PATH})
    target_link_libraries(${PROJECT_NAME} ${CUDA_cudadevrt_LIBRARY})
endif()

Вот набор теоретически похожих команд компиляции (результат, по крайней мере, такой же):

nvcc -dc --gpu-architecture=compute_52 -m64 main.cu -o main.dc.obj
nvcc -dlink --gpu-architecture=compute_52 -m64 main.dc.obj -o main.obj
link /SUBSYSTEM:CONSOLE /LIBPATH:"%CUDA_PATH%\lib\x64" main.obj main.dc.obj cudart_static.lib cudadevrt.lib cublas.lib cublas_device.lib

1 ответ

Оказывается, что nvcc -dlink не сообщает об отсутствующих зависимостях и просто счастливо продолжает работу без каких-либо ошибок. Решение проблемы заключается в том, что cublas_device.lib должны быть связаны как во время соединения с хостом, так и с устройством, то есть команды компиляции должны выглядеть следующим образом:

nvcc -dc --gpu-architecture=compute_52 -m64 main.cu -o main.dc.obj
nvcc -dlink --gpu-architecture=compute_52 -m64 -lcublas_device main.dc.obj -o main.obj
link /SUBSYSTEM:CONSOLE /LIBPATH:"%CUDA_PATH%\lib\x64" main.obj main.dc.obj cudart_static.lib cudadevrt.lib cublas.lib cublas_device.lib

Также, nvcc -dlink зависит от порядка, но противоположным образом, к которому привык ld: -lcublas_device должен появиться перед объектными файлами, которые этого требуют.

На стороне CMake вещей, cuda_add_cublas_to_target не может добавить cublas_device.lib к команде link устройства и добавляет ее только к команде host link. В качестве обходного пути добавьте зависимость явно в список флагов nvcc:

list(APPEND CUDA_NVCC_FLAGS -lcublas_device)
Другие вопросы по тегам