CUDA 12.4文档4 编程接口之使用NVCC编译

2024-04-13 13:44

本文主要是介绍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编译的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/900301

相关文章

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

Spring Security简介、使用与最佳实践

《SpringSecurity简介、使用与最佳实践》SpringSecurity是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架,本文给大家介绍SpringSec... 目录一、如何理解 Spring Security?—— 核心思想二、如何在 Java 项目中使用?——

springboot中使用okhttp3的小结

《springboot中使用okhttp3的小结》OkHttp3是一个JavaHTTP客户端,可以处理各种请求类型,比如GET、POST、PUT等,并且支持高效的HTTP连接池、请求和响应缓存、以及异... 在 Spring Boot 项目中使用 OkHttp3 进行 HTTP 请求是一个高效且流行的方式。

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

Java使用Javassist动态生成HelloWorld类

《Java使用Javassist动态生成HelloWorld类》Javassist是一个非常强大的字节码操作和定义库,它允许开发者在运行时创建新的类或者修改现有的类,本文将简单介绍如何使用Javass... 目录1. Javassist简介2. 环境准备3. 动态生成HelloWorld类3.1 创建CtC

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

C#使用Spire.Doc for .NET实现HTML转Word的高效方案

《C#使用Spire.Docfor.NET实现HTML转Word的高效方案》在Web开发中,HTML内容的生成与处理是高频需求,然而,当用户需要将HTML页面或动态生成的HTML字符串转换为Wor... 目录引言一、html转Word的典型场景与挑战二、用 Spire.Doc 实现 HTML 转 Word1

C#实现一键批量合并PDF文档

《C#实现一键批量合并PDF文档》这篇文章主要为大家详细介绍了如何使用C#实现一键批量合并PDF文档功能,文中的示例代码简洁易懂,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言效果展示功能实现1、添加文件2、文件分组(书签)3、定义页码范围4、自定义显示5、定义页面尺寸6、PDF批量合并7、其他方法

SpringBoot实现不同接口指定上传文件大小的具体步骤

《SpringBoot实现不同接口指定上传文件大小的具体步骤》:本文主要介绍在SpringBoot中通过自定义注解、AOP拦截和配置文件实现不同接口上传文件大小限制的方法,强调需设置全局阈值远大于... 目录一  springboot实现不同接口指定文件大小1.1 思路说明1.2 工程启动说明二 具体实施2