NVIDIA Ampere GPU架构的CUDA应用程序兼容性指南

基于NVIDIA安培GPU架构构建CUDA应用程序的指南。

1. NVIDIA安培GPU架构兼容性

1.1. 关于本文档

本应用说明《NVIDIA Ampere GPU架构CUDA应用兼容性指南》旨在帮助开发者确保其NVIDIA® CUDA®应用程序能够在基于NVIDIA® Ampere架构的GPU上运行。本文档为熟悉CUDA C++编程的开发者提供指导,帮助他们确保软件应用与NVIDIA Ampere GPU架构兼容。

1.2. NVIDIA安培GPU架构上的应用兼容性

CUDA应用程序二进制文件(包含一个或多个GPU内核)可以以两种形式包含已编译的GPU代码:二进制cubin对象和每个内核的前向兼容PTX汇编。cubin和PTX都是针对特定目标计算能力生成的。为某个计算能力生成的cubin支持在具有相同主版本号和相同或更高次版本号计算能力的GPU上运行。例如,为计算能力7.0生成的cubin支持在计算能力7.5的GPU上运行,但为计算能力7.5生成的cubin支持在计算能力7.0的GPU上运行,而为计算能力7.x生成的cubin支持在计算能力8.x的GPU上运行。

内核也可以编译为PTX格式。在应用程序加载时,PTX会被编译为cubin,然后使用该cubin执行内核。与cubin不同,PTX具有向前兼容性。这意味着PTX支持在任何计算能力高于生成该PTX时假设的计算能力的GPU上运行。例如,为计算能力7.x生成的PTX代码可以支持在计算能力7.x或任何更高版本(主版本或次版本)上运行,包括计算能力8.x。因此,虽然这是可选的,但建议所有应用程序都应包含内核的PTX以确保向前兼容性。要了解更多关于cubin和PTX兼容性的信息,请参阅编程指南中的使用NVCC编译。

当CUDA应用程序在GPU上启动内核时,CUDA运行时会检测系统中GPU的计算能力,并利用该信息寻找与之最匹配的内核cubin或PTX版本。如果二进制文件中存在与该GPU兼容的cubin,则直接使用该cubin执行。否则,CUDA运行时会先通过即时编译1PTX生成兼容的cubin,随后使用该cubin执行。若既无兼容cubin也无PTX可用,则内核启动将失败。

包含内核PTX版本的应用二进制文件,应可直接在基于NVIDIA安培架构的GPU上运行。此类情况下无需重新构建应用程序。但若应用二进制文件未包含PTX(仅包含cubins),则需重新构建才能在基于NVIDIA安培架构的GPU上运行。要了解更多关于构建兼容应用的信息,请阅读Building Applications with the NVIDIA Ampere GPU Architecture Support

1.3. 验证现有应用对Ampere架构的兼容性

使CUDA应用程序兼容NVIDIA Ampere GPU架构的第一步是检查应用程序二进制文件是否已包含兼容的GPU代码(至少包含PTX)。以下部分将说明如何为已构建的CUDA应用程序实现这一目标。

1.3.1. 基于CUDA Toolkit 10.2或更早版本构建的应用程序

使用CUDA Toolkit 2.1至10.2版本构建的CUDA应用程序,只要其内核包含PTX版本,即可与基于NVIDIA Ampere架构的GPU兼容。可通过以下步骤强制在应用程序加载时进行PTX到JIT的编译来测试兼容性:

当设置CUDA_FORCE_PTX_JIT=1时,应用程序二进制文件中嵌入的GPU二进制代码将被忽略。相反,每个内核的PTX代码将通过即时编译(JIT)生成GPU二进制代码。如果应用程序不包含PTX代码,则执行将失败。这意味着该应用程序与NVIDIA Ampere GPU架构不兼容,需要重新构建以获得兼容性。另一方面,如果应用程序在此环境变量设置下正常工作,则表明该应用程序与NVIDIA Ampere GPU架构兼容。

注意

测试完成后请务必取消设置CUDA_FORCE_PTX_JIT环境变量。

1.3.2. 基于CUDA Toolkit 11.0构建的应用程序

使用CUDA Toolkit 11.0构建的CUDA应用程序与NVIDIA Ampere GPU架构兼容,只要它们构建时包含原生cubin(计算能力8.0)或PTX形式的内核,或两者兼有。

1.4. 基于NVIDIA Ampere GPU架构支持构建应用

根据用于构建应用程序的CUDA Toolkit版本,可以构建包含针对NVIDIA Ampere GPU架构的PTX和/或原生cubin。虽然仅包含PTX就足够,但包含原生cubin还具有以下优势:

  • 它节省了终端用户JIT编译仅以PTX形式提供的内核所需的时间。所有没有原生cubin的内核都会从PTX进行JIT编译,包括链接到应用程序的所有库中的内核,即使这些内核从未被应用程序启动过。特别是在使用大型库时,这种JIT编译可能会耗费大量时间。CUDA驱动程序会缓存PTX JIT生成的cubin,因此对用户来说这主要是一次性成本,但最好尽可能避免这种时间消耗。

  • PTX即时编译的内核通常无法利用新型GPU的架构特性,这意味着原生编译的cubin可能速度更快或精度更高。

1.4.1. 使用CUDA Toolkit 10.x或更早版本构建应用程序

CUDA Toolkit 10.x版本(10.0、10.1和10.2)中包含的nvcc编译器可以生成本地支持Volta和Turing架构(计算能力7.x)的cubin文件。使用CUDA Toolkit 10.x时,为确保nvcc能为所有近期GPU架构生成cubin文件,同时生成PTX版本以实现与未来GPU架构的前向兼容,需在nvcc命令行中指定适当的-gencode=参数,如下例所示。

Windows

nvcc.exe -ccbin "C:\vs2010\VC\bin"
  -Xcompiler "/EHsc /W3 /nologo /O2 /Zi /MT"
  -gencode=arch=compute_52,code=sm_52
  -gencode=arch=compute_60,code=sm_60
  -gencode=arch=compute_61,code=sm_61
  -gencode=arch=compute_70,code=sm_70
  -gencode=arch=compute_75,code=sm_75
  -gencode=arch=compute_75,code=compute_75
  --compile -o "Release\mykernel.cu.obj" "mykernel.cu"

Mac/Linux

/usr/local/cuda/bin/nvcc
  -gencode=arch=compute_52,code=sm_52
  -gencode=arch=compute_60,code=sm_60
  -gencode=arch=compute_61,code=sm_61
  -gencode=arch=compute_70,code=sm_70
  -gencode=arch=compute_75,code=sm_75
  -gencode=arch=compute_75,code=compute_75
  -O2 -o mykernel.o -c mykernel.cu

或者,也可以使用简化的nvcc命令行选项-arch=sm_XX。它相当于上面使用的更详细的-gencode=命令行选项的简写形式。-arch=sm_XX会扩展为以下内容:

-gencode=arch=compute_XX,code=sm_XX
-gencode=arch=compute_XX,code=compute_XX

然而,虽然-arch=sm_XX命令行选项默认确实会包含PTX后端目标二进制文件,但它每次只能指定一个目标cubin架构,并且无法在同一条nvcc命令行中使用多个-arch=选项,这就是为什么上述示例显式使用-gencode=的原因。

对于10.0版本之前的CUDA工具包,需要根据特定工具包版本支持的架构移除一个或多个-gencode选项(例如,CUDA工具包9.x最高支持_60和_61架构)。同时需要更新用于生成PTX的最终-gencode参数——更多信息和示例请参阅特定CUDA工具包版本的文档。

注意

compute_XX 指代PTX版本,而 sm_XX 指代cubin版本。nvcc-gencode= 命令行选项中的 arch= 子句指定前端编译目标,必须始终是PTX版本。code= 子句指定后端编译目标,可以是cubin或PTX或两者。只有 code= 子句指定的后端目标版本会被保留在最终二进制文件中;至少应包含一个PTX版本以确保与未来架构的兼容性。

1.4.2. 使用CUDA Toolkit 11.0构建应用程序

从CUDA Toolkit 11.0版本开始,nvcc能够生成原生支持NVIDIA安培GPU架构(计算能力8.0)的cubin文件。使用CUDA Toolkit 11.0时,为确保nvcc能为所有近期GPU架构生成cubin文件,同时生成PTX版本以保持与未来GPU架构的前向兼容性,需按照以下示例在nvcc命令行中指定相应的-gencode=参数。

Windows

nvcc.exe -ccbin "C:\vs2010\VC\bin"
  -Xcompiler "/EHsc /W3 /nologo /O2 /Zi /MT"
  -gencode=arch=compute_52,code=sm_52
  -gencode=arch=compute_60,code=sm_60
  -gencode=arch=compute_61,code=sm_61
  -gencode=arch=compute_70,code=sm_70
  -gencode=arch=compute_75,code=sm_75
  -gencode=arch=compute_80,code=sm_80
  -gencode=arch=compute_80,code=compute_80
  --compile -o "Release\mykernel.cu.obj" "mykernel.cu"

Mac/Linux

/usr/local/cuda/bin/nvcc
  -gencode=arch=compute_52,code=sm_52
  -gencode=arch=compute_60,code=sm_60
  -gencode=arch=compute_61,code=sm_61
  -gencode=arch=compute_70,code=sm_70
  -gencode=arch=compute_75,code=sm_75
  -gencode=arch=compute_80,code=sm_80
  -gencode=arch=compute_80,code=compute_80
  -O2 -o mykernel.o -c mykernel.cu

注意

compute_XX 指代PTX版本,而 sm_XX 指代cubin版本。nvcc-gencode= 命令行选项中的 arch= 子句指定前端编译目标,必须始终是PTX版本。code= 子句指定后端编译目标,可以是cubin或PTX或两者。只有 code= 子句指定的后端目标版本会被保留在最终二进制文件中;至少应包含一个PTX版本以确保与未来架构的兼容性。

1.4.3. 独立线程调度兼容性

自Volta架构起,NVIDIA GPU在warp内的线程间实现了独立线程调度功能。若开发者此前对warp同步性2存在假设,该特性可能导致实际执行代码的线程集合与旧架构有所不同。具体细节及修正方案请参阅编程指南中的计算能力7.0章节。为协助开发者迁移至NVIDIA Ampere GPU架构,可通过以下编译器选项组合启用Pascal调度模型。

nvcc -gencode=arch=compute_60,code=sm_80 ...

2. 版本历史

版本 1.0

  • 首次公开发布。

3. 通知

3.1. 注意事项

本文档仅供信息参考之用,不应视为对产品功能、状态或质量的保证。NVIDIA公司(“NVIDIA”)对本文件所含信息的准确性或完整性不作任何明示或暗示的陈述或保证,并对其中可能存在的错误不承担任何责任。NVIDIA对于因使用此类信息而产生的后果、或因使用该信息导致的第三方专利或其他权利侵权概不负责。本文件不构成对开发、发布或交付任何材料(定义见下文)、代码或功能的承诺。

NVIDIA保留随时对本文件进行更正、修改、增强、改进以及任何其他变更的权利,恕不另行通知。

客户在下单前应获取最新的相关信息,并确认这些信息是最新且完整的。

除非NVIDIA与客户授权代表签署的单独销售协议中另有约定,否则NVIDIA产品的销售均以订单确认时提供的NVIDIA标准销售条款和条件为准(以下简称"销售条款")。NVIDIA特此明确反对将任何客户通用条款适用于本文件所述NVIDIA产品的采购。本文件不直接或间接构成任何合同义务。

NVIDIA产品并非设计、授权或保证适用于医疗、军事、航空、航天或生命支持设备,也不适用于那些可以合理预期NVIDIA产品故障或失灵会导致人身伤害、死亡、财产或环境损害的应用场景。NVIDIA对于在此类设备或应用中使用和/或包含NVIDIA产品不承担任何责任,因此客户需自行承担相关风险。

NVIDIA不声明或保证基于本文档的产品适用于任何特定用途。NVIDIA未必会对每个产品的所有参数进行测试。客户应全权负责评估和确定本文档所含信息的适用性,确保产品适合并满足客户计划的应用需求,并执行必要的应用测试以避免应用或产品出现故障。客户产品设计中的缺陷可能会影响NVIDIA产品的质量和可靠性,并可能导致超出本文档范围的其他或不同的条件和/或要求。对于任何因以下原因导致的故障、损坏、成本或问题,NVIDIA不承担任何责任:(i) 以违反本文档的任何方式使用NVIDIA产品或(ii) 客户产品设计。

本文档不授予任何NVIDIA专利权、版权或其他NVIDIA知识产权的明示或暗示许可。NVIDIA发布的关于第三方产品或服务的信息,不构成NVIDIA对这些产品或服务的使用许可或担保认可。使用此类信息可能需要获得第三方基于其专利或其他知识产权的许可,或需要获得NVIDIA基于其专利或其他知识产权的许可。

本文件中的信息仅可在获得NVIDIA事先书面批准、未经改动完整复制且完全符合所有适用的出口法律法规,并附带所有相关条件、限制和声明的情况下进行复制。

本文件及所有NVIDIA设计规格、参考板、文件、图纸、诊断工具、清单和其他文档(统称及单独称为"材料")均以"现状"提供。NVIDIA不对材料作出任何明示或默示的保证,包括但不限于对不侵权、适销性和特定用途适用性的默示保证免责。在法律允许的最大范围内,NVIDIA不就因使用本文件导致的任何损害承担责任,包括但不限于任何直接、间接、特殊、附带、惩罚性或后果性损害,无论损害成因如何,也无论责任理论为何,即使NVIDIA已被告知发生此类损害的可能性。不论客户因任何原因可能遭受的任何损害,NVIDIA对客户就本文所述产品的全部及累计责任应受产品销售条款的限制。

3.2. OpenCL

OpenCL是苹果公司的商标,经Khronos Group Inc.授权使用。

3.3. 商标

NVIDIA和NVIDIA标识是美国及其他国家NVIDIA公司的商标或注册商标。其他公司及产品名称可能是其各自关联公司的商标。

1

即时编译

2

Warp-synchronous(线程束同步)指的是一个假设,即同一线程束中的线程在每条指令处都是同步的,因此可以在无需显式同步的情况下进行值传递等操作。