正文:
NVCC的编译过程总体可以用一个图进行描述:
NVCC的编译过程分为离线编译和即时编译两部分组成:
离线编译(绿色虚线框内):
CUDA源程序(即xxx.cu文件)在编译前的预处理会被分为主机端代码和设备段代码(即图中的左右分支):
1.如图右分支:在设备端代码会被编译成ptx文件(可以看作是用于设备端的汇编文件)或是直接可运行的二进制文件xxx.cubin,然后将起.ptx/.cubin文件放在fatbinary文件中。
2.如图左分支:在主机端代码进行预处理,并将其嵌入到fatbinary文件中,并将CUDA特定的C++扩展转换成标准C++结构(通过cudafe++和cudafe1.stub.c合成为。cudafe1.cpp),然后C++主机编译器将所合成的主机代码与嵌入的fatbinary编译成主机.o/.obj文件。
即时编译(图片绿色虚线框下方):
在主机设备启动代码时,CUDA run-time系统会对fatbinary文件进行检测,以获得一个对于GPU设备合适的映像(之后还会提及):
1.如果之前的cubin文件与当前GPU相匹配,run-time系统通过nvlink对多个设备端文件进行链接,最后通过host linker链接主机端文件成可执行文件。
2.如果cubin文件所表示的虚拟设备与当前GPU不符或者fatbinary文件中只包含ptx文件,将会对fatbinary文件中的ptx文件进行即时编译,并对其进行链接(nvlink)最后通过host linker链接主机端文件成可执行文件。
补充:
NVCC极大的考虑到了应用的向后兼容性,(如最上面图的绿色实线宽内)将输入设备端代码根据虚拟gpu结构(virtual architecture)编译成ptx,以及通过当前的真实gpu结构将其编译成cubin文件,到时进行直接执行即可。(如图1:virtual architecture)

由于ptx的存在,可以提高其兼容性,通过在运行时对ptx进行即时编译成cubin文件并执行。(图2:Just-in-Time Compilation)

nvcc可以通过命令进行设置相应的virtual compute architecture和real sm architecture
nvcc xxx.cu -arch=compute_30 -code=sm_30
其中 -arch=compute_30 是指对虚拟gpu体系结构配置为计算能力为3.0,生成相应的ptx;-code=sm_30则是将ptx文件编译成sm为3.0的cubin二进制文件。
注意:-arch 的配置一定要低于-code ,否者是无法进行编译的。
由于nvcc编译是支持向后编译的,ptx是由虚拟体系结构进行编译的,而现实版本比虚拟gpu体系结构还要低,这会导致无法运行。
nvcc编译过程第二篇:https://blog.youkuaiyun.com/shungry/article/details/89788342
想了解更多可以直接看官方nvcc文档:https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html