【问题标题】:cuModuleLoadDataEx ignores all optionscuModuleLoadDataEx 忽略所有选项
【发布时间】:2013-06-08 19:11:45
【问题描述】:

这个问题类似于cuModuleLoadDataEx options,但我想再次提出这个话题并提供更多信息。

当使用 NV 驱动程序通过 cuModuleLoadDataEx 加载 PTX 字符串时,它似乎忽略了所有选项。我提供了完整的工作示例,以便任何有兴趣的人都可以直接轻松地复制它。首先是一个小的 PTX 内核(另存为 small.ptx),然后是加载 PTX 内核的 C++ 程序。

.version 3.1
.target sm_20, texmode_independent
.address_size 64
.entry main()
{
        ret;
}

main.cc

#include<cstdlib>
#include<iostream>
#include<fstream>
#include<sstream>
#include<string>
#include<map>
#include "cuda.h"

int main(int argc,char *argv[])
{
  CUdevice cuDevice;
  CUcontext cuContext;

  CUfunction func;
  CUresult ret;
  CUmodule cuModule;

  cuInit(0);

  std::cout << "trying to get device 0\n";
  ret = cuDeviceGet(&cuDevice, 0);
  if (ret != CUDA_SUCCESS) { exit(1);}

  std::cout << "trying to create a context\n";
  ret = cuCtxCreate(&cuContext, 0, cuDevice);
  if (ret != CUDA_SUCCESS) { exit(1);}

  std::cout << "loading PTX string from file " << argv[1] << "\n";

  std::ifstream ptxfile( argv[1] );
  std::stringstream buffer;
  buffer << ptxfile.rdbuf();
  ptxfile.close();

  std::string ptx_kernel = buffer.str();

  std::cout << "Loading PTX kernel with driver\n" << ptx_kernel;

  const unsigned int jitNumOptions = 3;
  CUjit_option *jitOptions = new CUjit_option[jitNumOptions];
  void **jitOptVals = new void*[jitNumOptions];

  // set up size of compilation log buffer                                                                                                     
  jitOptions[0] = CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES;
  int jitLogBufferSize = 1024*1024;
  jitOptVals[0] = (void *)&jitLogBufferSize;

  // set up pointer to the compilation log buffer                                                                                              
  jitOptions[1] = CU_JIT_INFO_LOG_BUFFER;
  char *jitLogBuffer = new char[jitLogBufferSize];
  jitOptVals[1] = jitLogBuffer;

  // set up wall clock time                                                                                                                    
  jitOptions[2] = CU_JIT_WALL_TIME;
  float jitTime = -2.0;
  jitOptVals[2] = &jitTime;

  ret = cuModuleLoadDataEx( &cuModule , ptx_kernel.c_str() , jitNumOptions, jitOptions, (void **)jitOptVals );
  if (ret != CUDA_SUCCESS) { exit(1);}

  std::cout << "walltime: " << jitTime << "\n";
  std::cout << std::string(jitLogBuffer) << "\n";
}

构建(假设CUDA安装在/usr/local/cuda下,我用的是CUDA 5.0):

g++ -I/usr/local/cuda/include -L/usr/local/cuda/lib64/ main.cc -o main -lcuda

如果有人能够从编译过程中提取任何有意义的信息,那就太好了! CUDA 驱动程序 API 的文档,其中解释了 cuModuleLoadDataEx(以及它应该接受哪些选项)http://docs.nvidia.com/cuda/cuda-driver-api/index.html

如果我运行它,日志是空的,并且 NV 驱动程序甚至都没有触及 jitTime

./main small.ptx
trying to get device 0
trying to create a context
loading PTX string from file empty.ptx
Loading PTX kernel with driver
.version 3.1
.target sm_20, texmode_independent
.address_size 64
.entry main()
{
    ret;
}

walltime: -2

编辑:

我设法获得了 JIT 编译时间。然而,驱动程序似乎需要一个 32 位值的数组作为 OptVals。不像手册中所说的那样,作为我的系统 64 位上的指针数组 (void *)。所以,这行得通:

const unsigned int jitNumOptions = 1;
CUjit_option *jitOptions = new CUjit_option[jitNumOptions];
int *jitOptVals = new int[jitNumOptions];
jitOptions[0] = CU_JIT_WALL_TIME;
// here the call to cuModuleLoadDataEx
std::cout << "walltime: " << (float)jitOptions[0] << "\n";

我相信不可能对void * 的数组做同样的事情。以下代码不起作用:

const unsigned int jitNumOptions = 1;
CUjit_option *jitOptions = new CUjit_option[jitNumOptions];
void **jitOptVals = new void*[jitNumOptions];
jitOptions[0] = CU_JIT_WALL_TIME;
// here the call to cuModuleLoadDataEx
// here I also would have a problem casting a 64 bit void * to a float (32 bit)

编辑

查看 JIT 编译时间 jitOptVals[0] 具有误导性。如 cmets 中所述,JIT 编译器缓存以前的翻译,如果找到缓存的编译,则不会更新 JIT 编译时间。由于我正在查看此值是否已更改,因此我假设该调用忽略了所有选项。它没有。效果很好。

【问题讨论】:

    标签: c++ cuda ptx


    【解决方案1】:

    您的 jitOptVals 不应包含指向您的值的指针,而是将值转换为 void*

    // set up size of compilation log buffer
    jitOptions[0] = CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES;
    int jitLogBufferSize = 1024*1024;
    jitOptVals[0] = (void *)jitLogBufferSize;
    
    // set up pointer to the compilation log buffer
    jitOptions[1] = CU_JIT_INFO_LOG_BUFFER;
    char *jitLogBuffer = new char[jitLogBufferSize];
    jitOptVals[1] = jitLogBuffer;
    
    // set up wall clock time
    jitOptions[2] = CU_JIT_WALL_TIME;
    float jitTime = -2.0;
    //Keep jitOptVals[2] empty as it only an Output value:
    //jitOptVals[2] = (void*)jitTime;
    

    cuModuleLoadDataEx 之后,你会得到你的jitTime,比如jitTime = (float)jitOptions[2];

    【讨论】:

    • 感谢您的回答!我在 64 位系统上。编译器不会让我将浮点数转换为 void*。这个接口是否只适用于 32 位指针?
    • 无论是在 32 位还是 64 位系统上,驱动程序都只接受 32 位 void 指针。难以置信的愚蠢。因此,在 64 位系统上,解决方案是不使用 **void(如手册中所述),而是使用 *int。他们一定是在开玩笑。
    • 不,它也适用于 64 位。但是对于 jit-time,您必须首先将 64 位指针转换为 32 位整数,然后将这些位读取为浮点数: int opt_int = (int)jitOptVals[2];浮动* opt_float = (float*)&opt_int;浮动 jitTime = *opt_float;
    • 有可能。在 32 位系统上传递 32 位指针,在 64 位系统上传递 64 位指针。它总是一个 void* 而不仅仅是一个 32 位 int。
    • 按照你想要的方式进行投射,你只需要前 32 位。是的,我在发布之前测试了这些东西。从 SDK 中获取 matrixMulDrv 示例,就像一个魅力。日志缓冲区的问题可能是没有输出,因为每个 ptx 编译都由驱动程序缓存...... cuModuleLoadDataEx 之后的 jitOptVals[0] 的值是多少?它应该是写入缓冲区的字符数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    相关资源
    最近更新 更多