CUDA编译过程

流程

  1. 将test.cu代码进行分离,利用cudafe.exe 去分离CPU代码和GPU代码,我们可以在生成的中间文件可以看到test.cudafe1.cpp和test.cudafe1.gpu
  2. cicc.exe 将根据编译选项-arch=compute_xx将GPU代码编译成对应架构的test.ptx文件
  3. ptxas.exe 编译 test.ptx 到test.cubin,这个是根据编译选项-code=sm_xx定义的,比如test.sm_30.cubin.(这一步叫做PTX离线编译,主要的目的是为了将代码编译成一个确定的计算能力和SM版本,对应的版本信息保存在cubin中)
  4. fatbin.exe 编译test .cubin 和test. ptx到 text.fatbin.c 。 (这一步叫PTX在线编译,是将cubin和ptx中的版本信息保存在fatbin中)
  5. 调用系统的gcc/g++将host代码(test.cudafe1.cpp)和fatbin(text.fatbin.c)编译成对应的目标文件test.o 和test._dlink.o。
  6. 用c++编译器将目标文件链接起来生成可执行文件。

实验

nvcc --cuda test.cu --keep --dryrun

细节

  • -arch=compute_XX, -code=sm_XX, 如果写两个的话必须这样来写,也就说compute_必须对应的是arch, code必须对应的是sm_,arch代表的是目标机器(vitural),而code代表的是真实机器(real),下面是具体的例子:

nvcc -o test test.cu -arch=compute_35 -code=sm_70 --keep --verbose

具体小步骤
  1. cicc *** -arch compute_35 -o test.ptx// 可以看出ptx是根据arch来设定的
  2. ptxas -arch=sm_70 -m64 “test.ptx” -o “test.cubin”//本地二进制文件是根据sm_70来设定,至于为用的是arch,这就是nvcc瞎写
  3. fatbinary --create=“test.fatbin” -64 “–image=profile=sm_70,file=test.cubin” --embedded-fatbin=“test.fatbin.c” --cuda(这里面没有将ptx放进去不知道什么情况,当只有arch一个参数的时候ptx和cubin都会放入fatbin.c里面)

使用

一般都是只使用一个-arch, 这样默认你的arch和code是同一个架构算力,比如-arch=sm_70,这个在nvcc -help中可以看到,就是为了方便而已,等效于-arch=compute_70, -code=sm_70, 感觉英伟达这搞得一点也不规范。

思考

  • 经常可以看到说cuda的即时编译,可是我是没见到运行的时候出现编译过程,难道是我使用姿势不对?

fatbinary机制。exe二进制文件中会包含一个或多个体系结构的二进制代码以及PTX代码来完全避免JIT成本。CUDA运行时会在二进制文件中查找当前GPU架构的代码,并在找到时运行它。如果找不到二进制代码,但PTX可用,则驱动程序将编译PTX代码。这样,部署的CUDA应用程序可以在新GPU出现时支持它们。nvcc x.cu -arch=compute_10 -code=compute_10,sm_10,sm_13,比如这一段程序,编译出来的代码就会有10,13两个二进制,实际遇到了这类GPU就直接使用,否则就把compute_10.ptx运行时编译一波。

  • 难道我一份exe每次在新机器A上重复使用时每次都要即时编译吗?这也太蠢了吧

缓存机制。 如果在code中没有指示出来实际运行的GPU, 理论来说你在A这个GPU上运行的时候,每次都要JIT,为此cuda做了一个优化,就是将它第一次接触过得GPU卡即时编译后缓存一起,也就是说第一次在A卡编译后,下次再运行就直接可以调用缓存里面的二进制了,理论上来说就是放在-code=sm_10, A,sm_20,不过A是在遇到A之后才编译的

注意

-arch 的配置一定要低于-code ,想想看,你一个-arch=compute_70的 **.ptx很难去编译出一个code=sm_30的二进制代码,因为很多架构是70的机器上的特性,在30的机器上压根都没有,比如tensorcore什么的,所以这个要注意。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
CUDA是一个用于并行计算的平台和编程模型,专门设计用于NVIDIA GPU。在编译CUDA程序时,可以采取一些优化措施以提高性能。以下是一些常用的CUDA编译优化技术: 1. 使用合适的编译器选项:在编译CUDA程序时,可以通过选择合适的编译器选项来控制优化级别。例如,可以使用-O3选项开启所有优化选项,或者使用-O2选项开启一组常用的优化选项。 2. 使用合适的函数修饰符:CUDA提供了一些函数修饰符,如__global__和__device__,用于标识并行执行的函数和设备函数。正确使用这些修饰符可以帮助编译器进行更好的优化。 3. 减少内存访问:由于GPU的计算能力通常比内存访问能力更强,减少内存访问可以提高性能。可以尝试通过使用共享内存、本地内存等技术来减少全局内存访问。 4. 矢量化和并行化:CUDA编译器可以自动将某些代码向量化或并行化,以提高执行效率。可以尝试使用适当的数据结构和算法,以促进矢量化和并行化。 5. 优化存储器访问模式:在CUDA程序中,可以尝试通过访问连续内存块、使用缓存和纹理内存等技术来优化存储器访问模式。 6. 使用计算能力特定的优化:不同的NVIDIA GPU具有不同的计算能力和架构特点。可以根据目标设备的计算能力和架构特点,针对性地进行优化。 需要注意的是,CUDA编译优化是一个复杂的主题,具体的优化策略和技术可能因应用场景而异。在实际开发过程中,可以结合性能分析工具和调试器,进行针对性的优化和性能调优。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值