2016-09-19 17 views
1

に存在している場合、私は、次の最小限の.cuファイル「不明なエラー」CUBLASはカーネル

#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への呼び出しを削除すると、cudaMalloc0(エラーなし)を返します。

原因は何でしょうか?それをどうやって修正することができますか?動的並列処理を使用するカーネルからCUBLASを呼び出す必要があります。which is theoretically supported "コールを削除するだけです"というオプションはありません。ここ

は、対応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 
+0

を私が間違っていない限り、あなたが実行可能ファイルに掲載しており、そのソースをコンパイルして実行することは不可能であろう。問題を再現するためにそのソースをコンパイルして実行する方法を説明するために質問を編集できますか? – talonmies

+0

なぜそれは不可能でしょうか? 'nvcc'を使ってうまくコンパイルします – Joe

+0

正確なコンパイルコマンドとコンパイラのバージョンを編集してください。 AFAIK独立したコンパイルの軌道は 'main'と別にコンパイルされたカーネルコードを同じファイルに持つことができません – talonmies

答えて

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が順序に依存するが、その逆の方法で、 1つはldから-lcublas_deviceになる必要があります。の前に、より前に表示する必要があります。

物事のCMake側では、cuda_add_cublas_to_targetはdevice linkコマンドにcublas_device.libを追加できず、host linkコマンドにのみ追加します。回避策として、NVCCフラグのリストに明示的に依存関係を追加します。

list(APPEND CUDA_NVCC_FLAGS -lcublas_device) 
+0

Linuxのツールチェーンでは、デバイスリンクフェーズで依存関係が失われても命令は失敗します。私は実際には、実行可能な実行可能ファイルを作成するために、デバイスコンパイルとグローバルリンク(デバイスリンクなし)が必要だと思います。これがうまくいくかどうかの私の混乱は、デバイスコンパイル段階から来ています。99%は、以前のツールチェーンバージョンではデバイスコードを発行しないので、 'main'は失われているはずです。次に、重複がなくてもmainをコンパイルしようとしていたはずです。しかし、デバイスのリンクは微妙で、間違っているのは簡単です。 – talonmies

+0

はい、1回のコールで最後の2つのステップを実行することはできますが、cmakeは2回の別々の呼び出しを行います。 Linuxだけでも可能なはずです。 – Joe

関連する問題