nvcc编译过程第一篇:https://blog.csdn.net/shungry/article/details/89715468


正文:编译流程(补充)

以我mytest.cu为例子,输入以下命令:

nvcc --cuda .\mytest.cu -keep 

先解释里面命令的含义,

--cuda/-cuda是将.cu文件编译成一个.cu.cpp.ii的文件;

--keep/-keep是指保留所有在中间层生成的文件;

在命令行中查看生成信息(或直接点开相应文件夹),出现以下结果:

Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2019/4/30     14:31        1212818 mytest.cpp1.ii
-a----        2019/4/30     14:31            294 mytest.cpp1.ii.res
-a----        2019/4/30     14:31        1079606 mytest.cpp4.ii
-a----        2019/4/30     14:31            244 mytest.cpp4.ii.res
-a----        2019/4/28     20:18           2810 mytest.cu
-a----        2019/4/30     14:31        1341211 mytest.cu.cpp.ii
-a----        2019/4/30     14:31            175 mytest.cu.cpp.ii.res
-a----        2019/4/30     14:31            274 mytest.cudafe1.c
-a----        2019/4/30     14:31         654595 mytest.cudafe1.cpp
-a----        2019/4/30     14:31           6664 mytest.cudafe1.gpu
-a----        2019/4/30     14:31           1546 mytest.cudafe1.stub.c
-a----        2019/4/30     14:31           4704 mytest.fatbin
-a----        2019/4/30     14:31          13926 mytest.fatbin.c
-a----        2019/4/30     14:31             27 mytest.module_id
-a----        2019/4/30     14:31           2970 mytest.ptx
-a----        2019/4/30     14:31           3496 mytest.sm_30.cubin

我们可以结合上一篇文章的图进行理解:https://blog.csdn.net/shungry/article/details/89715468

其中关注几个文件:

mytest.cpp1.ii为nvcc进行预处理时将.cu文件分离的device的部分;同理,mytest.cpp4.ii则是host端的代码部分(但文件中只有路径信息,我有点迷糊)。

mytest.ptx类似汇编用于device端的代码。

mytest.sm_30.cubin用于device端的二进制文件,由于我所用的电脑计算能力为3.0,所以编译二进制时自动编译为sm_30。

mytest.fatbin.c用于存放.cubin和.ptx的文件,如果你用vim查看文件,你会发现文件内只有一个数组,这应该就是是存.cubin/.ptx文件的地方:

static const __declspec(allocate(__CUDAFATBINDATASECTION)) unsigned long long fatbinData[]= {.../*这里省略*/...}

mytest.cuda1.*文件则是对以上文件的包含和调用,结合上一篇文章理解会更明白。

接下来输入以下命令:

 nvcc mytest.cu -keep -dryrun

将会得到整个编译的过程:由于是vs编译环境起cl.exe就充当了C++ Preprocessor的功能,右边分支得到.cpp1.ii 。经过cicc进行编译成ptx文件。ptx在通过ptxas文件进行根据当前设备环境进一步的编译得到.cubin文件。最后创建fatbinary包括ptx和cubin文件,转化为.fatbin.c文件。(根据下面命令理解整个过程会更加清晰)

#$ cl.exe > "mytest.cpp1.ii" -D__CUDA_ARCH__=300 -nologo -E -TP  -DCUDA_DOUBLE_MATH_FUNCTIONS -D__CUDACC__ -D__NVCC__  ......
#$ cicc --microsoft_version=1903 --msvc_target_version=1903 --compiler_bindir "......" --allow_managed  -arch compute_30 -m64 -ftz=0 -prec_div=1 -prec_sqrt=1 -fmad=1 --include_file_name "mytest.fatbin.c" -tused -nvvmir-library "......" --gen_module_id_file --module_id_file_name "mytest.module_id" --orig_src_file_name "mytest.cu" --gen_c_file_name "mytest.cudafe1.c" --stub_file_name "mytest.cudafe1.stub.c" --gen_device_file_name "mytest.cudafe1.gpu"  "mytest.cpp1.ii" -o "mytest.ptx"
#$ ptxas -arch=sm_30 -m64 "mytest.ptx"  -o "mytest.sm_30.cubin"
#$ fatbinary --create="mytest.fatbin" -64 --cmdline="" "--image=profile=sm_30,file=mytest.sm_30.cubin" "--image=profile=compute_30,file=mytest.ptx" --embedded-fatbin="mytest.fatbin.c" --cuda

在左分支,也是先进行预处理得到mytest.cpp4.ii,再通过cudafe++将.cudafe1.stub.c和.cpp4.ii合成为.cudafe1.cpp,最后编译为.o/.obj文件。

#$ cl.exe > "mytest.cpp4.ii" -nologo -E -TP -D__CUDACC__ -D__NVCC__  "-IC:...... -D "__CUDACC_VER_BUILD__=176" -D "__CUDACC_VER_MINOR__=0" -D "__CUDACC_VER_MAJOR__=9" -FI "cuda_runtime.h" -EHsc "mytest.cu"
#$ cudafe++ --microsoft_version=1903 --msvc_target_version=1903 --compiler_bindir "......" --allow_managed --m64 --parse_templates --gen_c_file_name "mytest.cudafe1.cpp" --stub_file_name "mytest.cudafe1.stub.c" --module_id_file_name "mytest.module_id" "mytest.cpp4.ii"
#$ cl.exe -Fo"mytest.obj" -D__CUDA_ARCH__=300 -nologo -c -TP  -DCUDA_DOUBLE_MATH_FUNCTIONS "......"   -EHsc "mytest.cudafe1.cpp"

最后通过nvlink对多个.cubin文件进行链接存入fatbinary中,同样转化为.fatbin.c文件,最后组成link.stub文件。通过编译器进行编译,最后通过host链接器继续链接执行。

#$ nvlink --arch=sm_30 --register-link-binaries="a_dlink.reg.c" -m64   "......" -cpu-arch=X86_64 "mytest.obj"  -o "a_dlink.sm_30.cubin"
#$ fatbinary --create="a_dlink.fatbin" -64 --cmdline="" -link "--image=profile=sm_30,file=a_dlink.sm_30.cubin" --embedded-fatbin="a_dlink.fatbin.c"
#$ cl.exe -Fo"a_dlink.obj" -nologo -c -TP -DFATBINFILE="\"a_dlink.fatbin.c\"" -DREGISTERLINKBINARYFILE="\"a_dlink.reg.c\"" -I. "......"   -D "__CUDACC_VER_BUILD__=176" -D "__CUDACC_VER_MINOR__=0" -D "__CUDACC_VER_MAJOR__=9" -EHsc "......
#$ cl.exe -Fe"a.exe" -nologo "a_dlink.obj" "mytest.obj" -link -INCREMENTAL:NO   "......devrt.lib  cudart_static.lib

整体来说,我对细节部分把握的还是十分有限,但是结合上一篇的流程图理解起来就形象很多。

NVCC命令

nvcc的所有命令可以直接通过输入命令“ nvcc -h ”来查看,也可以通过查看nvcc官方文档,nvcc命令分为以下几种(是nvcc官方文档定义的):

1.File and Path Specifications:这个和平时的gcc编译选项很相似,如“-o”,“-l”,等。

2.Options for Specifying the Compilation Phase:这一类指定nvcc编译的输出,“-cuda”输出.ii文件

3.Options for Specifying Behavior of Compiler/Linker:让编译器执行相应功能,如“-g”就是提供debug信息,“-O”编译优化的等级

4.Options for Passing Specific Phase Options

5.Options for Guiding the Compiler Driver:对nvcc的编译进行指导,如“-keep”,“-dryrun”只编译不执行

6.Options for Steering CUDA Compilation:???(--default-stream)指定命令发送到默认流上。

7.Options for Steering GPU Code Generation:生成gpu相关的命令,如“-arch”,“-code”

8.Generic Tool Options:一些帮助的工具“-V”,“-h”等


nvcc编译过程第三篇:https://blog.csdn.net/shungry/article/details/89842993

想了解更多可以直接看官方nvcc文档:https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐