"неизвестная ошибка" в первом 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)