本文主要是介绍CUDA 12.4文档4 编程接口之使用NVCC编译,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本博客参考官方文档进行介绍,全网仅此一家进行中文翻译,走过路过不要错过。
官方网址:https://docs.nvidia.com/cuda/cuda-c-programming-guide/
本文档分成多个博客进行介绍,在本人专栏中含有所有内容:
https://blog.csdn.net/qq_33345365/category_12610860.html
CUDA 12.4为2024年3月2日发表,本专栏开始书写日期2024/4/8,当时最新版本4.1
本人会维护一个总版本,一个小章节的版本,总版本会持续更新,小版本会及时的调整错误和不合理的翻译,内容大部分使用chatGPT 4翻译,部分内容人工调整
开始编辑时间:2024/4/8;最后编辑时间:2024/4/13
第六章 编程接口
CUDA C++为熟悉C++编程语言的用户提供了一个简单的路径,可以轻松地编写用于设备执行的程序。
它由C++语言的最小扩展和一个运行时库组成。
核心语言扩展已在编程模型章节中介绍。它们允许程序员将内核定义为一个C++函数,并使用一些新的语法来指定网格和块维度,每次调用该函数时使用。所有扩展的完整描述可以在C++语言扩展章节中找到。任何包含这些扩展的源文件都必须使用nvcc编译,如在NVCC编译章节中概述的那样。
运行时在CUDA运行时章节中介绍。它提供在主机上执行的C和C++函数,用于分配和释放设备内存,传输主机内存和设备内存之间的数据,管理多设备系统等。运行时的完整描述可以在CUDA参考手册中找到。
运行时是在一个更低级别的C API之上构建的,即CUDA驱动程序API,该API也可由应用程序访问。驱动程序API通过公开诸如CUDA上下文(设备的主机进程的类似物)和CUDA模块(设备的动态加载库的类似物)等较低级别概念,提供了额外的控制级别。大多数应用程序不使用驱动程序API,因为它们不需要这种额外的控制级别,而当使用运行时时,上下文和模块管理是隐式的,从而使代码更加简洁。由于运行时与驱动程序API互通,因此,大多数需要使用驱动程序API功能的应用程序可以默认使用运行时API,并且只在需要的时候使用驱动程序API。驱动程序API在驱动程序API章节中介绍,并在参考手册中完全描述。
6.1 使用NVCC编译
内核可以使用CUDA指令集架构编写,称为PTX,其在PTX参考手册中有描述。然而,通常使用如C++这样的高级编程语言更有效。在这两种情况下,内核必须由nvcc编译成二进制代码以在设备上执行。
nvcc是一个编译器驱动程序,简化了编译C++或PTX代码的过程:它提供简单且熟悉的命令行选项,并通过调用实现不同编译阶段的工具集来执行它们。本节给出了nvcc工作流程和命令选项的概述。完整的描述可以在nvcc用户手册中找到。
6.1.1 编译工作流
6.1.1.1 离线编译
使用nvcc编译的源文件可以包含一些主机代码(即,在主机上执行的代码)和设备代码(即,在设备上执行的代码)的混合。 nvcc的基本工作流程包括将设备代码从主机代码中分离出来,然后:
- 将设备代码编译成汇编形式(PTX代码)和/或二进制形式(cubin对象),
- 并通过替换内核中引入的<<<…>>>语法(在执行配置中有更详细的描述)修改主机代码,从PTX代码和/或cubin对象加载和启动每个编译好的内核所需的CUDA运行时函数调用。
修改的主机代码输出为C++代码,该代码将留待使用其他工具进行编译,或者通过让nvcc在最后的编译阶段调用主机编译器,直接以对象代码的形式输出。
然后,应用程序可以:
- 链接到已编译的主机代码(这是最常见的情况),
- 或者忽略修改的主机代码(如果有的话)并使用CUDA驱动程序API(参见驱动程序API)来加载和执行PTX代码或cubin对象。
6.1.1.2 实时编译 Just-in-Time Compilation
任何在运行时由应用程序加载的PTX代码都将由设备驱动程序进一步编译为二进制代码。这被称为即时编译。即时编译会增加应用程序的加载时间,但允许应用程序受益于每个新设备驱动程序带来的任何新的编译器改进。这也是应用程序在编译时尚不存在的设备上运行的唯一方式,如在应用程序兼容性章节中详细描述的那样。
当设备驱动程序为某些应用程序即时编译一些PTX代码时,它会自动缓存生成的二进制代码的一个副本,以避免在随后的应用程序调用中重复编译。缓存 - 称为计算缓存 - 在升级设备驱动程序时会自动失效,以便应用程序可以从内置在设备驱动程序中的新即时编译器的改进中受益。
环境变量可用于控制即时编译,如在CUDA环境变量章节中所描述的那样。
作为使用nvcc编译CUDA C++设备代码的替代方案,可以使用NVRTC在运行时将CUDA C++设备代码编译为PTX。 NVRTC是一个用于CUDA C++的运行时编译库;更多信息可以在NVRTC用户指南中找到。
6.1.2 二进制兼容性 Binary Compatibility
二进制代码是特定于架构的。 使用编译器选项-code生成cubin对象,该选项指定目标架构:例如,使用-code=sm_80编译将为计算能力为8.0的设备生成二进制代码。 从一个次要版本到下一个次要版本保证了二进制兼容性,但在一个次要版本到上一个次要版本或者在主要版本之间并不保证。换句话说,为计算能力X.y生成的cubin对象只能在计算能力为X.z的设备上执行,其中 z > y z>y z>y。
6.1.3 PTX兼容性
一些PTX指令只在具有更高计算能力的设备上支持。例如,Warp Shuffle函数只在计算能力为5.0及以上的设备上支持。-arch编译器选项指定在将C++编译为PTX代码时假定的计算能力。因此,包含warp shuffle的代码,例如,必须使用-arch=compute_50(或更高)进行编译。
为某特定计算能力生产的PTX代码总是可以编译为具有更大或等同计算能力的二进制代码。注意,从早期PTX版本编译的二进制文件可能无法使用某些硬件功能。例如,针对计算能力为7.0(Volta)的设备的二进制目标,由为计算能力6.0(Pascal)生成的PTX编译,不会使用Tensor Core指令,因为Pascal上没有这些功能。因此,最终的二进制文件可能比使用最新版本的PTX生成的二进制文件性能差。
编译为目标架构条件特性的PTX代码只在完全相同的物理架构上运行,其他地方无法运行。架构条件PTX代码不具有向前和向后的兼容性。例如,使用sm_90a或compute_90a编译的代码只能在计算能力为9.0的设备上运行,而且不向后或向前兼容。
6.1.4 应用兼容性
要在具有特定计算能力的设备上执行代码,应用程序必须加载与此计算能力兼容的二进制或PTX代码,如在二进制兼容性章节和PTX兼容性章节中所述。特别是,要能够在具有更高计算能力的未来架构上执行代码(对于这些架构,尚无法生成二进制代码),应用程序必须加载将为这些设备进行即时编译的PTX代码(参见即时编译章节)。
在CUDA C++应用程序中嵌入哪些PTX和二进制代码由-arch和-code编译器选项或-gencode编译器选项控制,详情请见nvcc用户手册。例如:
nvcc x.cu -gencode arch=compute_50,code=sm_50 -gencode arch=compute_60,code=sm_60 -gencode arch=compute_70,code=\"compute_70,sm_70\"
嵌入与计算能力5.0和6.0兼容的二进制代码(第一和第二个-gencode选项)以及与计算能力7.0兼容的PTX和二进制代码(第三个-gencode选项)。
生成主代码以在运行时自动选择最合适的代码进行加载和执行,上述示例将会是:
- 对于计算能力为5.0和5.2的设备,执行5.0的二进制代码,
- 对于计算能力为6.0和6.1的设备,执行6.0的二进制代码,
- 对于计算能力为7.0和7.5的设备,执行7.0的二进制代码,
- 对于计算能力为8.0和8.6的设备,执行在运行时编译为二进制代码的PTX代码。
例如,x.cu可以有一个优化的代码路径,该路径使用Warp Reduction操作,这些操作只在计算能力为8.0及以上的设备上支持。__CUDA_ARCH__宏可以用来区分基于计算能力的各种代码路径。它仅为设备代码定义。例如,使用-arch=compute_80编译时,__CUDA_ARCH__等于800。
如果x.cu针对架构条件特性以sm_90a或compute_90a编译,代码只能在计算能力为9.0的设备上运行。
使用驱动API的应用程序必须将代码编译为单独的文件,并在运行时显式加载和执行最合适的文件。
Volta架构引入了独立线程调度,这改变了GPU上线程的调度方式。对于依赖于前一架构中SIMT调度的特定行为的代码,独立线程调度可能会改变参与的线程集,导致结果不正确。为了在实施独立线程调度中详细描述的的纠正操作时帮助迁移,Volta开发者可以选择使用编译器选项组合-arch=compute_60 -code=sm_70以选择Pascal的线程调度。
nvcc用户手册列出了-arch、-code和-gencode编译器选项的各种简写。例如,-arch=sm_70是-arch=compute_70 -code=compute_70,sm_70的简写(它与-gencode arch=compute_70,code="compute_70,sm_70"相同)。
6.1.5 C++兼容性
编译器的前端按照C++语法规则处理CUDA源文件。主机代码支持完整的C++。然而,对于设备代码,只有一部分C++得到了完全支持,如在C++语言支持章节中所述。
6.1.6 64位兼容性
nvcc的64位版本以64位模式编译设备代码(即,指针为64位)。只有与64位模式的主机代码结合使用时,64位模式编译的设备代码才受支持。
这篇关于CUDA 12.4文档4 编程接口之使用NVCC编译的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!