如何在运行时生成,编译和运行CUDA内核

时间:2013-11-07 14:28:53

标签: cuda compilation gpgpu ptx

好吧,我有一个非常微妙的问题:)

让我们从我拥有的东西开始:

  1. 数据,大​​量数据,复制到GPU
  2. 由CPU(主机)生成的
  3. 程序,需要针对该阵列中的每个数据进行评估
  4. 程序更改非常频繁,可以在每次更改后生成CUDA字符串,PTX字符串或其他内容(?)和需要重新评估
  5. 我想要的:基本上只是想让它尽可能有效(快速),例如。避免将CUDA编译为PTX。解决方案甚至可以完全针对特定设备,这里不需要很大的兼容性:)

    我所知道的:我已经知道函数 cuLoadModule ,它可以从存储在文件中的PTX代码加载和创建内核。但我想,必须有一些其他方法可以直接创建内核,而不必先将其保存到文件中。或者也许可以将其存储为字节码?

    我的问题:你会怎么做?您可以发布一个示例或链接到类似主题的网站吗? TY

      

    编辑:好了,现在,PTX内核可以直接run from PTX字符串(字符数组)。无论如何我仍然想知道,有没有更好/更快的解决方案呢?仍然存在从字符串到某些PTX字节码的转换,应该可以避免。我还怀疑,从PTX创建设备特定Cuda二进制文件的一些聪明方法可能存在,这将消除JIT编译器延迟(很小,但如果你有大量的内核要运行它可以加起来):)

1 个答案:

答案 0 :(得分:4)

在他的评论中,Roger Dahl将以下帖子链接起来

Passing the PTX program to the CUDA driver directly

其中使用了两个函数,即cuModuleLoadcuModuleLoadDataEx。前者用于从文件加载PTX代码并将其传递给nvcc编译器驱动程序。后者避免了I / O并且能够将PTX代码作为C字符串传递给驱动程序。在任何一种情况下,您都需要准备好PTX代码,作为编译CUDA内核的结果(要加载或复制并粘贴在C字符串中)或作为手写源。

但是如果你必须从CUDA内核开始动态创建PTX代码会怎么样?按照CUDA Expression templates中的方法,您可以定义包含CUDA内核的字符串,如

ss << "extern \"C\" __global__ void kernel( ";
ss << def_line.str() << ", unsigned int vector_size, unsigned int number_of_used_threads ) { \n";
ss << "\tint idx = blockDim.x * blockIdx.x + threadIdx.x; \n";
ss << "\tfor(unsigned int i = 0; i < ";
ss << "(vector_size + number_of_used_threads - 1) / number_of_used_threads; ++i) {\n";
ss << "\t\tif(idx < vector_size) { \n";
ss << "\t\t\t" << eval_line.str() << "\n";
ss << "\t\t\tidx += number_of_used_threads;\n";
ss << "\t\t}\n";
ss << "\t}\n";
ss << "}\n\n\n\n";

然后使用系统调用将其编译为

int nvcc_exit_status = system(
         (std::string(NVCC) + " -ptx " + NVCC_FLAGS + " " + kernel_filename 
              + " -o " + kernel_comp_filename).c_str()
    );

    if (nvcc_exit_status) {
            std::cerr << "ERROR: nvcc exits with status code: " << nvcc_exit_status << std::endl;
            exit(1);
    }

最后使用cuModuleLoadcuModuleGetFunction从文件加载PTX代码并将其传递给编译器驱动程序,如

    result = cuModuleLoad(&cuModule, kernel_comp_filename.c_str());
    assert(result == CUDA_SUCCESS);
    result =  cuModuleGetFunction(&cuFunction, cuModule, "kernel");
    assert(result == CUDA_SUCCESS);

当然,表达模板与此问题无关,我只是引用了我在这个答案中报告的想法的来源。