2016-09-27 10 views
0

アプリケーションのパフォーマンスを向上させるために、CUDAカーネルをnvrtc JITコンパイラでコンパイルする必要があります(命令フェッチの量が増えますが、複数の配列アクセスを保存しています)。cuModuleGetFunctionが返されない

このようにして(その重要ではありません)私のファンクション・ジェネレータによって生成されます。私は、以下の機能を備えた上記のコードをコンパイルしています

extern "C" __device__ void GetSumOfBranches(double* branches, double* outSum) 
{ 
    double sum = (branches[38])+(-branches[334])+(-branches[398])+(-branches[411]); 
    *outSum = sum; 
} 

CUfunction* FunctionGenerator::CreateFunction(const char* programText) 
{ 
     // When I comment this statement out the output of the PTX file is changing 
     // what is the reson?! 
     // Bug? 
     std::string savedString = std::string(programText); 


     nvrtcProgram prog; 
     nvrtcCreateProgram(&prog, programText, "GetSumOfBranches.cu", 0, NULL, NULL); 

     const char *opts[] = {"--gpu-architecture=compute_52", "--fmad=false"}; 
     nvrtcCompileProgram(prog, 2, opts); 

     // Obtain compilation log from the program. 
     size_t logSize; 
     nvrtcGetProgramLogSize(prog, &logSize); 
     char *log = new char[logSize]; 
     nvrtcGetProgramLog(prog, log); 
     // Obtain PTX from the program. 
     size_t ptxSize; 
     nvrtcGetPTXSize(prog, &ptxSize); 
     char *ptx = new char[ptxSize]; 
     nvrtcGetPTX(prog, ptx); 

     printf("%s", ptx); 

     CUdevice cuDevice; 
     CUcontext context; 
     CUmodule module; 
     CUfunction* kernel; 
     kernel = (CUfunction*)malloc(sizeof(CUfunction)); 
     cuInit(0); 
     cuDeviceGet(&cuDevice, 0); 
     cuCtxCreate(&context, 0, cuDevice); 
     auto resultLoad = cuModuleLoadDataEx(&module, ptx, 0, 0, 0); 
     auto resultGetF = cuModuleGetFunction(kernel, module, "GetSumOfBranches"); 
     return kernel; 
} 

すべてはそのcuModuleGetFunctionを除いて取り組んでいるがCUDA_ERROR_NOT_FOUNDを返しています。このエラーは、GetSumOfBranchesがPTXファイル内に見つからないために発生します。

printf("%s", ptx);の出力がこれですが:私のoptinionで

// Generated by NVIDIA NVVM Compiler 
// 
// Compiler Build ID: CL-19856038 
// Cuda compilation tools, release 7.5, V7.5.17 
// Based on LLVM 3.4svn 
// 

.version 4.3 
.target sm_52 
.address_size 64 

    // .globl GetSumOfBranches 

.visible .func GetSumOfBranches(
    .param .b64 GetSumOfBranches_param_0, 
    .param .b64 GetSumOfBranches_param_1 
) 
{ 
    .reg .f64 %fd<8>; 
    .reg .b64 %rd<3>; 


    ld.param.u64 %rd1, [GetSumOfBranches_param_0]; 
    ld.param.u64 %rd2, [GetSumOfBranches_param_1]; 
    ld.f64 %fd1, [%rd1+304]; 
    ld.f64 %fd2, [%rd1+2672]; 
    sub.rn.f64 %fd3, %fd1, %fd2; 
    ld.f64 %fd4, [%rd1+3184]; 
    sub.rn.f64 %fd5, %fd3, %fd4; 
    ld.f64 %fd6, [%rd1+3288]; 
    sub.rn.f64 %fd7, %fd5, %fd6; 
    st.f64 [%rd2], %fd7; 
    ret; 
} 

すべてが正常であるとGetSumOfBranchescuModuleGetFunctionによって発見さsould。なぜ私に説明できますか?私は、PTXの出力だけであるstd::string savedString = std::string(programText);をoutcomment

2番目の質問

// Generated by NVIDIA NVVM Compiler 
// 
// Compiler Build ID: CL-19856038 
// Cuda compilation tools, release 7.5, V7.5.17 
// Based on LLVM 3.4svn 
// 

.version 4.3 
.target sm_52 
.address_size 64 

savedStringは一切使用しておりませんので、これは奇妙です...

+3

なぜあなたは '__device__'とマークされた問題の関数を持っていますか?これはCUDAカーネルではありません。ホストコードから呼び出すことはできません。とにかく、「なぜこれは機能しないのですか?」という質問に対してはあなたは[mcve]を提供するはずです –

+0

私はそれについて私はちょうどカーネルをコンパイルしているとは考えていません..私は私もデバイスの機能をコンパイルできると思っています。あなたはちょうど私の問題を解決しました(多分あなたはポイントを得るために私の質問に答えたいです - それ以外の場合はありがとう)。次の質問では、私は最小で完全で検証可能な例を提供します。 – Jens

答えて

2

あなたがしようとしていることはサポートされていません。ホスト側のモジュール管理APIとデバイスELF形式は、__device__関数を公開せず、カーネル起動API経由で呼び出し可能な関数は__global__のみです。

デバイス関数を事前または実行時にコンパイルし、JIT形式でカーネルとリンクすることができます。これらのカーネルを取得して呼び出すことができます。しかし、それはあなたができるすべてです。