在线编译单个CUDA功能

时间:2014-04-02 23:14:10

标签: cuda compilation

我的程序中有一个名为float valueAt(float3 v)的函数。它应该在给定点返回函数的值。该功能是用户指定的。我目前有这个功能的翻译,但是其他人建议我在网上编译这个功能,所以它在机器代码中更快。

我该怎么做?我相信我知道如何在生成PTX时加载该功能,但我不知道如何生成PTX。

2 个答案:

答案 0 :(得分:3)

CUDA无法运行非PTX代码的运行时编译。

您可以做什么,但不能使用标准CUDA API。 PyCUDA为CUDA C代码提供了一种优雅的即时编译方法,其中包括工具链的幕后分支,以编译为设备代码并使用运行时API加载。 (可能的)缺点是您需要在应用程序的顶层使用Python,如果要将代码发送给第三方,您可能还需要发布一个可用的Python发行版。

我能想到的另一个替代方案是OpenCL,它支持运行时编译(直到最近才支持它)。 C99语言库比CUDA提供的限制更多,我发现API非常冗长,但运行时编译模型运行良好。

答案 1 :(得分:2)

我已经考虑过这个问题了一段时间,虽然我不认为这是一个很好的"解决方案,它似乎确实有效,所以我想我会分享它。

基本思想是使用linux生成进程来编译然后运行已编译的代码。我认为这几乎是不费脑子的,但是因为我把这些部分放在一起,所以我会在这里发布说明,以防它对其他人有用。

问题中的问题陈述是能够获取包含用户定义函数的文件,假设它是单个变量f(x)的函数,即{{1} },x和y可以用y = f(x)数量表示。

用户将编辑包含所需功能的名为float的文件。该文件必须符合C语法规则。

fx.txt:

fx.txt

然后,该文件将包含在将保留它的y=1/x 函数中:

user_testfunc.cuh:

__device__

包含在通过包装器调用的内核中。

cudalib.cu:

__device__ float fx(float x){
  float y;
#include "fx.txt"
;
  return y;
}

cudalib.h:

#include <math.h>
#include "cudalib.h"
#include "user_testfunc.cuh"

__global__ void my_kernel(float x, float *y){

  *y = fx(x);
}

float cudalib_compute_fx(float x){
  float *d, *h_d;
  h_d = (float *)malloc(sizeof(float));
  cudaMalloc(&d, sizeof(float));
  my_kernel<<<1,1>>>(x, d);
  cudaMemcpy(h_d, d, sizeof(float), cudaMemcpyDeviceToHost);
  return *h_d;
  }

上述文件内置于共享库中:

float cudalib_compute_fx(float x);

我们需要一个主应用程序来使用这个共享库。

t452.cu:

nvcc -arch=sm_20 -Xcompiler -fPIC -shared cudalib.cu -o libmycudalib.so

编译如下:

#include <stdio.h>
#include <stdlib.h>
#include "cudalib.h"

int main(int argc, char* argv[]){

  if (argc == 1){
    //  recompile lib, and spawn new process
    int retval = system("nvcc -arch=sm_20 -Xcompiler -fPIC -shared cudalib.cu -o libmycudalib.so");
    char scmd[128];
    sprintf(scmd, "%s skip", argv[0]);
    retval = system(scmd);}
  else { // compute f(x) at x = 2.0
    printf("Result is: %f\n", cudalib_compute_fx(2.0));
    }
  return 0;
}

此时,主应用程序(nvcc -arch=sm_20 -o t452 t452.cu -L. -lmycudalib )可以执行,它将产生f(2.0)的结果,在这种情况下为0.5:

t452

然后,用户可以修改$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./t452 Result is: 0.500000 文件:

fx.txt

只需重新运行应用程序,即可使用新的功能行为:

$ vi fx.txt
$ cat fx.txt
y = 5/x

此方法利用了以下事实:在重新编译/替换共享库时,新的linux进程将获取新的共享库。另请注意,为清楚起见,我省略了几种错误检查。至少我会检查CUDA错误,我也可能在重新编译之前删除共享对象(.so)库,然后在编译后测试它的存在,以进行编译成功进行的基本测试。

此方法完全使用运行时API来实现此目标,因此用户必须在其计算机上安装CUDA工具包并进行适当设置,以便PATH中可以使用$ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./t452 Result is: 2.500000 。使用带有PTX代码的驱动程序API可以使此过程更加清晰(并且不需要用户计算机上的工具包),但AFAIK无法在不使用nvcc或者不使用nvcc的情况下从CUDA C生成PTX用户创建的工具链构建在nvidia llvm编译器工具之上。在未来,可能会有更多的整合&#34; &#34;标准&#34;中可用的方法CUDA C工具链,或者甚至是驱动程序。

可以使用设备代码的单独编译和链接来安排类似的方法,以便需要向用户公开的唯一源代码位于user_testfunc.cu(和fx.txt)。

编辑:现在有一个CUDA runtime compilation facility,应该用它来代替上述内容。

相关问题