CUDA C++ Programming Guide——编程接口 Compilation with NVCC

    科技2025-06-23  23

    Programming Interface

    CUDA C ++为熟悉C ++编程语言的用户提供了一条简单的路径,可以轻松编写程序以供设备执行。它由对C ++语言的最小扩展集和运行时库组成。 核心语言扩展已在“编程模型”中引入。它们允许程序员将内核定义为C ++函数,并在每次调用该函数时使用一些新语法指定网格和块尺寸。有关所有扩展的完整说明,请参见C ++语言扩展。包含其中一些扩展名的任何源文件都必须使用nvcc进行编译,如使用NVCC进行编译中所述。运行时在CUDA运行时中引入。它提供了C和C ++函数,这些函数可以在主机上执行以分配和取消分配设备内存,在主机内存和设备内存之间传输数据,管理具有多个设备的系统等。有关运行时的完整说明,请参见CUDA参考手册。

    运行时建立在较低级C API CUDA驱动程序API的基础上,应用程序也可以访问它。通过展示诸如CUDA上下文(设备的主机进程的类似物)和CUDA模块(设备的动态加载库的类似物)之类的低级概念,驱动程序API提供了更高级别的控制。大多数应用程序不使用驱动程序API,因为它们不需要此附加控制级别,并且在使用运行时时,上下文和模块管理是隐式的,从而使代码更简洁。由于运行时可与驱动程序API互操作,因此大多数需要某些驱动程序API功能的应用程序可以默认使用运行时API,而仅在需要时使用驱动程序API。该驱动程序API是在驱动程序API中引入的,并且在参考手册中有完整描述。

    Compilation with NVCC

    可以使用称为PTX的CUDA指令集体系结构来编写内核,在PTX参考手册中对此进行了描述。 但是,使用高级编程语言(例如C ++)通常更有效。 在这两种情况下,内核都必须由nvcc编译为二进制代码才能在设备上执行。nvcc是一个编译器驱动程序,可简化C ++或PTX代码的编译过程:它提供简单且熟悉的命令行选项,并通过调用实现不同编译阶段的工具集合来执行它们。 本节概述了nvcc工作流程和命令选项。 完整的描述可以在nvcc用户手册中找到。

    Compilation Workflow

    Offline Compilation

    使用nvcc编译的源文件可以包含主机代码(即在主机上执行的代码)和设备代码(即在设备上执行的代码)的混合。 nvcc的基本工作流程是将设备代码与主机代码分开,然后,将设备代码编译为汇编形式(PTX代码)和/或二进制形式(cubin对象),并通过用必要的CUDA运行时函数调用替换内核中引入的<<< … >>>语法(在执行配置中有更详细的描述)来修改主机代码,以从PTX代码加载和启动每个编译的内核,并/或cubin对象。修改后的主机代码要么作为C ++代码输出,然后使用其他工具进行编译,要么通过在最后一个编译阶段让nvcc调用主机编译器直接作为目标代码输出。

    应用程序可以:链接到已编译的主机代码(这是最常见的情况),或忽略修改后的主机代码(如果有),并使用CUDA驱动程序API(请参阅驱动程序API)加载并执行PTX代码或cubin对象。

    Just-in-Time Compilation

    **应用程序在运行时加载的任何PTX代码都会由设备驱动程序进一步编译为二进制代码。这称为即时编译。**即时编译会增加应用程序的加载时间,但允许应用程序受益于每个新设备驱动程序附带的所有新编译器改进。这也是应用程序在编译应用程序时不存在的设备上运行的唯一方法,如应用程序兼容性中所述。当设备驱动程序为某个应用程序及时编译某些PTX代码时,它会自动缓存生成的二进制代码的副本,以避免在后续的应用程序调用中重复进行编译。升级设备驱动程序后,缓存(称为计算缓存)会自动失效,因此应用程序可以受益于设备驱动程序内置的新即时编译器的改进。 如CUDA环境变量中所述,环境变量可用于控制即时编译。

    作为使用nvcc编译CUDA C ++设备代码的替代方法,NVRTC可用于在运行时将CUDA C ++设备代码编译为PTX。 NVRTC是用于CUDA C ++的运行时编译库;有关更多信息,请参见《 NVRTC用户指南》。

    Binary Compatibility

    二进制代码是特定于体系结构的。 使用指定目标体系结构的编译器选项-code生成cubin对象:例如,使用-code = sm_35进行编译将为计算能力为3.5的设备生成二进制代码。 从一个次要修订版本到下一个修订版本,可以保证二进制兼容性,但不能保证从一个次要修订版本到上一个修订版本或跨主要版本。 换句话说,为计算能力X.y生成的立方对象将仅在计算能力X.z的设备上执行,其中z≥y。

    注意:仅台式机支持二进制兼容性。 Tegra不支持此功能。 另外,不支持桌面和Tegra之间的二进制兼容性。

    PTX Compatibility

    某些PTX指令仅在具有更高计算能力的设备上受支持。 例如,仅在计算能力3.0及更高版本的设备上支持“扭曲混洗功能”。 -arch编译器选项指定将C ++编译为PTX代码时假定的计算能力。 因此,例如,包含warp shuffle的代码必须使用-arch = compute_30(或更高版本)进行编译。

    为某些特定的计算能力生成的PTX代码始终可以编译为具有更大或相等计算能力的二进制代码。 请注意,从较早的PTX版本编译的二进制文件可能未使用某些硬件功能。 例如,从针对计算能力6.0(Pascal)生成的PTX编译而来的计算能力7.0(Volta)的二进制目标设备将不使用Tensor Core指令,因为这些在Pascal上不可用。 结果,最终二进制文件的性能可能比使用最新版本的PTX生成二进制文件时的性能差。

    Application Compatibility

    要在具有特定计算功能的设备上执行代码,应用程序必须加载与二进制计算和PTX兼容性中所述的与此计算功能兼容的二进制或PTX代码。 特别是,为了能够在具有更高计算能力的未来架构上执行代码(尚无法为其生成二进制代码),应用程序必须加载将为这些设备及时编译的PTX代码(请参阅Just- 及时编译)。

    哪些PTX和二进制代码嵌入CUDA C ++应用程序中,由-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选项)和PTX和与计算能力7.0兼容的二进制代码(第三-gencode选项)。 生成主机代码以在运行时自动选择最合适的代码来加载和执行,在上面的示例中,该代码将是:

    5.0 binary code for devices with compute capability 5.0 and 5.2,6.0 binary code for devices with compute capability 6.0 and 6.1,7.0 binary code for devices with compute capability 7.0 and 7.5,PTX code which is compiled to binary code at runtime for devices with compute capability 8.0 and 8.6. x.cu可以具有一个优化的代码路径,例如,它使用warp shuffle操作,只有计算能力为3.0或更高的设备才支持。 __CUDA_ARCH__宏可用于根据计算能力来区分各种代码路径。仅针对设备代码定义。例如,使用-arch = compute_35进行编译时,__CUDA_ARCH__等于350。 使用驱动程序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 '相同)。

    C++ Compatibility

    编译器的前端根据C ++语法规则处理CUDA源文件。 主机代码支持完全C ++。 但是,如C ++语言支持中所述,设备代码仅完全支持C ++的子集。

    64-Bit Compatibility

    nvcc的64位版本以64位模式编译设备代码(即,指针为64位)。 只有以64位模式编译的主机代码才支持以64位模式编译的设备代码。同样,nvcc的32位版本以32位模式编译设备代码,而以32位模式编译的主机代码仅支持以32位模式编译的设备代码。nvcc的32位版本也可以使用-m64编译器选项以64位模式编译设备代码。nvcc的64位版本也可以使用-m32编译器选项以32位模式编译设备代码。

    Processed: 0.015, SQL: 8