CUDA 动态编译(NVRTC)简记
在linux上用sublime text 3上写完cuda代码和c++代码后,想用code::blocks去一并编译,就像visual studio那样一键编译运行,但发现在code::blocks上设定自定义编译器为nvcc时比较麻烦,所以想到了用nvrtc。
nvrtc中的rtc是runtime compile的意思,在visual studio(vs)里的一键编译其实是vs编译器替你干了很多底层的脏活,但到了linux,这些脏活就都得程序员来做了。。。
一、这些脏活都是什么呢?
1)vs把你的所有代码整理起来,并分类,用于在gpu里执行的device设备端代码,送往nvcc.exe里进行编译;用于在cpu里执行的host端代码,用vs自家的cl.exe编译
2)在最后的链接过程,vs把上面两个部分编译出的二进制代码融在一起成为一个exe。
二、那nvrtc能干啥呢?
1)nvrtc可以将原始的c++语法的cuda代码,编译成ptx文件,ptx就是parallel thread execution的缩写,一个ptx文件其实就跟txt差不多,用windows自带的记事本就能打开,打开之后会看到一堆类似汇编语法格式的东西,这个就是nvrtc根据我们的cuda源文件编译出的能在gpu上执行的代码,但是ptx代码和真正的gpu汇编还是有轻微的区别,但是区别很小,程序员可以通过查看编译出的ptx文件,窥知nvrtc编译器在编译的时候为我们的源码做了什么优化(举个简单的例子:比如浮点数a,b,c,当计算a*b+c这种线性运算的时候,一般都是先算a*b,再把结果与c相加,但是在ptx代码里会发现编译器直接用一个fmad指令,一次用硬件完成了浮点数的乘加操作)。
2)将上述过程产生的ptx文件,通过n卡driver api送入显卡直接执行。
三、为啥要用nvrtc?上面的nvcc不就够用了吗?
1)因为在linux里设定nvcc编译环境比较麻烦,有坑,而通过上面的对于nvrtc的叙述,我们发现整个编译过程如果利用nvrtc的话会很简单,坑少。
2)而且不用我们在编译器里设定nvcc编译环境了。
四、前提条件:
1)首先,要装一块n卡。(这句好像是废话......)
2)为这块显卡装合适的驱动。
(ps:linux装显卡驱动很麻烦,最好是一装完系统就装显卡驱动,然后再安装其它的那些软件,我一开始没经验,装了ubuntu后直接开装一堆软件,到最后想起要装显卡驱动的时候各种报错,实在没办法了只能重装系统,重装系统的时候选择不安装默认的nouveau显卡驱动。还有就是显卡驱动不要装太新版本的,装完一遍之后更新的时候也要小心,以免搞坏了连登录界面都进不去......)
3)装完显卡驱动后,再安装cuda toolkit,这里的坑没有上面多,但也要小心。
五、过程:
1)在一般的文本编辑器上写完c++和配套的cuda代码后,利用nvrtc将gpu代码编译成ptx。
2)利用gcc或者mingw(其它的也行)把在cpu端的代码编译成obj,链接成exe。(cpu端的代码里自然就会有利用driver api加载ptx代码的东西,以及一些kernel核函数调用时参数设置的东西)
3)测试你的程序是不是运行正常。
六、结果:
我在自己的机器上试了试上面的过程,能跑通,而且经上面的步骤,gpu代码也支持cuda纹理对象(cuda_texture_object),可以对cudatextureobject_t类型的对象进行纹理寻址。
七、存在的疑问:
1)六中,我测试了一下随机显存访问的性能,一个利用纹理对象,另一个利用平时的显存访问,结果显存访问比纹理拾取反而要快一倍(前者9us,后者16us),暂时不知道这是为啥。
2)网上有人说利用nvrtc编译出的ptx代码要比用nvcc编译器编译出的代码效率低,但是官方文档上是这么写的:
上面图片的意思是说nvrtc可以提供静态编译(nvcc)所不能提供的代码优化,也就是说官网上暗示nvrtc要比nvcc要快。
具体哪个对我现在暂时没做过实验。
推荐阅读