欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

CUDA 动态编译(NVRTC)简记

程序员文章站 2022-05-29 11:40:00
在linux上用sublime text 3上写完CUDA代码和c++代码后,想用code::blocks去一并编译,就像visual studio那样一键编译运行,但发现在code::blocks上设定自定义编译器为nvcc时比较麻烦,所以想到了用NVRTC。 NVRTC中的RTC是runtime ......

 在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编译器编译出的代码效率低,但是官方文档上是这么写的:

CUDA 动态编译(NVRTC)简记

  上面图片的意思是说nvrtc可以提供静态编译(nvcc)所不能提供的代码优化,也就是说官网上暗示nvrtc要比nvcc要快。

  具体哪个对我现在暂时没做过实验。