CUDA编程 - Programming Interface
- Compilation with NVCC(用NVCC编译)
- CUDA Runtime
- Initialization(初始化)
- Device Memory(设备内存)
- Shared Memory(共享内存)
- Page-Locked Host Memory(Page-Locked 主机内存)
- Asynchronous Concurrent Execution(异步并发执行)
- Multi-Device System(多设备系统)
- Unified Virtual Address Space(统一虚拟地址空间)
- Interprocess Communication(进程间通信)
- Error Checking(错误检查)
- Call Stack(调用堆栈)
- Texture and Surface Memory
- Graphics Interoperability(图形互操作性)
- External Resource Interoperability(外部资源互操作性)
- Versioning and Compatibility(版本与兼容性)
- Compute Modes(计算模式)
- Mode Switches(模式开关)
- Tesla Compute Cluster Mode for Windows(Windows的Tesla计算群集模式)
It consists of a minimal set of extensions to the C++ language and a runtime library.
- 将 kernel 定义成 C++ 函数 C++ Language Extensions
- 每次调用函数时,可以指定 grid 和 block 的大小和维度
- 必须使用 nvcc 编译 Compilation with NVCC
- CUDA Runtime,提供C和C++函数,可以在host主机上分配和取消分配设备内存,在主机内存和设备内存之间传输数据,管理多设备系统 CUDA Runtime
- runtime基于 lower-level C API(CUDA 驱动程序API)构建,应用程序可以访问该 API.
- CUDA 驱动程序API 通过 lower-level concepts 来实现 additional level of control Driver API
- CUDA 上下文,CUDA contexts
- 设备的主机进程的模拟,the analogue of host processes for the device
- CUDA 模块,CUDA modules
- 设备的动态加载库的模拟,the analogue of dynamically loaded libraries for the device
- CUDA 上下文和模块管理是隐式的
- CUDA 驱动程序API 通过 lower-level concepts 来实现 additional level of control Driver API
Compilation with NVCC(用NVCC编译)
使用PTX
CUDA指令集来编写kernel,kernel通过 nvcc
编译成二进制代码在设备上执行。
nvcc
是一个编译器驱动程序,可简化 C ++ 或 PTX 代码的编译过程:它提供简单且熟悉的命令行选项,并通过调用实现不同编译阶段的工具集合来执行它们。本节概述了 nvcc 工作流和命令选项。
Compilation Workflow(编译工作流)
-
Offline Compilation(离线编译)
nvcc编译的源文件包括:主机代码host code(主机上执行)和设备代码device code(设备上执行),nvcc的基本流程是将设备代码和主机代码分开;
- 将设备代码编译成汇编形式(PTX代码)或者二进制形式(cubin对象)
- 通过CUDA runtime 函数调用
<<<...>>>
修改主机代码,从 PTX代码 或者 cubin对象 加载和启动每个编译的kernel
修改后的主机代码可以以C ++代码输出,以便使用其他工具进行编译,也可以通过在最后一个编译阶段让
nvcc
调用主机编译器直接作为目标代码输出。应用程序可以:
- 链接到已编译的主机代码(这是最常见的情况),
- 忽略修改后的主机代码(如果有),并使用 CUDA驱动程序API 加载并执行 PTX代码 或 cubin对象。
-
Just-in-Time Compilation(即时编译)
应用程序在 runtime 时加载的任何 PTX代码,都会由设备驱动程序进一步编译为二进制代码binary code(存入缓存中,避免重复编译),但会消耗一定的加载时间。CUDA 环境变量可用于即时编译。
NVRTC 可以作为使用nvcc编译 CUDA C ++ 设备代码的替代方法,NVRTC可用于在 runtime 时将 CUDA C ++ 设备代码编译为 PTX。
Binary Compatibility(二进制兼容性)
次要版本具有向后兼容性,计算能力X.y生成的 cubin 对象将仅在计算能力X.z的设备上执行,其中z≥y。
PTX Compatibility(PTX兼容性)
某些PTX指令仅在具有更高计算能力的设备上受支持。
-arch
编译器选项指定将C++编译为PTX代码时假定的计算能力。 因此,例如,包含warp shuffle的代码必须使用-arch = compute_30
(或更高版本)进行编译。
为某些特定的计算能力生成的 PTX代码 始终可以编译为具有更大或相等计算能力的二进制代码。但由于较早的 PTX版本 编译的二进制文件可能未使用某些硬件功能,最终二进制文件的性能可能比使用最新版本的 PTX 生成二进制文件时的性能差。
Application Compatibility(应用程序兼容性)
要在具有特定计算功能的设备上执行代码,应用程序必须加载与二进制计算和PTX兼容性中所述的,与此计算功能兼容的及时编译的二进制或PTX代码。
-arch
和 -code
编译器选项或 -gencode
编译器选项,控制哪个PTX 和二进制代码嵌入 CUDA C ++应用程序中。
nvcc x.cu
// 嵌入与计算能力3.5和5.0兼容的二进制代码
-gencode arch=compute_35,code=sm_35
-gencode arch=compute_50,code=sm_50
// 嵌入与计算能力6.0兼容的PTX和二进制代码
-gencode arch=compute_60,code=\'compute_60,sm_60\'
生成主机代码,以在运行时自动选择最合适的代码来加载和执行,在上面的示例中,该代码将是:
- 具有计算能力3.5和3.7的设备的3.5二进制代码
- 具有计算能力5.0和5.2的设备的5.0二进制代码
- 具有计算能力6.0和6.1的设备的6.0二进制代码,
- PTX代码可在运行时编译为具有7.0或更高版本的计算能力的设备的二进制代码。
x.cu
可以具有一个优化的代码路径,例如,它使用warp shuffle操作,只有计算能力为3.0或更高的设备才支持。
__CUDA_ARCH__
宏可用于根据计算能力来区分各种设备代码路径。例如,当使用-arch = compute_35
进行编译时,__ CUDA_ARCH__ = 350
。
使用驱动程序API的应用程序编译代码,必须分离文件,并在运行时显式加载和执行最合适的文件。
nvcc
用户手册列出了-arch
,-code
和-gencode
编译器选项的各种简写形式。例如,-arch = sm_35
是-arch = compute_35-code = compute_35,sm_35
的简写,与-gencodearch = compute_35,code = \'compute_35,sm_35 \'
相同。
C++ Compatibility(C ++兼容性)
编译器的前端根据 C++语法规则 处理 CUDA源文件。
主机代码支持完全C++,设备代码仅完全支持 C++的子集。
64-Bit Compatibility(64位兼容性)
- nvcc的64位版本以64位模式编译设备代码(即,指针为64位),只有以64位模式编译的主机代码才支持以64位模式编译的设备代码。
- nvcc的32位版本以32位模式编译设备代码,只有以32位模式编译的主机代码才支持以32位模式编译的设备代码。
- nvcc的32位版本也可以使用
-m64
编译器选项以64位模式编译设备代码。 - nvcc的64位版本也可以使用-
m32
编译器选项以32位模式编译设备代码。
CUDA Runtime
在与应用程序链接的 cudart库 中实现了 runtime,可以通过 cudart.lib
或 libcudart.a
静态实现,也可以通过 cudart.dll
或 libcudart.so
动态实现。
需要 cudart.dll
和/或 cudart.so
进行动态链接的应用程序,通常会将它们作为应用程序安装包的一部分包含在内。只有在链接到 CUDA runtime 的同一实例的组件之间传递 CUDA runtime symbols 的地址才是安全的。
如异构编程中提到的那样,CUDA 编程模型假定一个由主机host 和设备device 组成的系统,每个主机和设备都有各自独立的内存。设备内存Device Memory 概述了用于管理设备内存的runtime 函数。
- 共享内存 Shared Memory :说明了线程层次结构中引入的共享内存的使用,以最大限度地提高性能。
- 页面锁定主机内存 Page-Locked Host Memory:引入了页面锁定主机内存,这是将 kernel 执行与主机和设备内存之间的数据传输重叠所必需的。
- 异步并发执行 Asynchronous Concurrent Execution:描述了用于在系统中的各个级别启用异步并发执行的概念和API。
- 多设备系统 Multi-Device System:展示了编程模型如何扩展到将多个设备连接到同一主机的系统。
- 错误检查 Error Checking:介绍了如何正确检查 runtime 生成的错误。
- 调用堆栈 Call Stack:提到用于管理 CUDA C++ 调用堆栈的 runtime 函数。
- 纹理和表面内存 Texture and Surface Memory:提供了纹理和表面内存空间,它们提供了另一种访问设备内存的方式。它们还公开了一部分GPU纹理化硬件。
- 图形互操作性 Texture and Surface Memory:介绍了 runtime 提供的与两种主要图形API(OpenGL和Direct3D)互操作的功能。
Initialization(初始化)
Device Memory(设备内存)
Shared Memory(共享内存)
Page-Locked Host Memory(Page-Locked 主机内存)
- Portable Memory(便携式内存)
- Write-Combining Memory
- Mapped Memory(映射内存)
Asynchronous Concurrent Execution(异步并发执行)
- Concurrent Execution between Host and Device(主机与设备之间的并发执行)
- Concurrent Kernel Execution(内核执行并发)
- Overlap of Data Transfer and Kernel Execution(数据传输和内核执行的重叠)
- Concurrent Data Transfers(数据传输并发)
- Streams
- Creation and Destruction
- Default Stream
- Explicit Synchronization(显式同步)
- Implicit Synchronization(隐式同步)
- Overlapping Behavior(重叠行为)
- Host Functions (Callbacks)(回调)
- Stream Priorities(流优先级)
- Graphs
- Graph Structure
- Node Types(节点类型)
- Creating a Graph Using Graph APIs(使用图APIs构建图)
- Creating a Graph Using Stream Capture(使用流捕获构建图)
- Cross-stream Dependencies and Events
- Prohibited and Unhandled Operations
- Invalidation
- Using Graph APIs
- Events
- Creation and Destruction(创建和销毁)
- Elapsed Time(经过的时间)
- Synchronous Calls(同步通信)
- Graph Structure
Multi-Device System(多设备系统)
- Device Enumeration(设备枚举)
- Device Selection(设备选择)
- Stream and Event Behavior(流与事件行为)
- Peer-to-Peer Memory Access(点对点内存访问)
- IOMMU on Linux(Linux上的IOMMU) - Peer-to-Peer Memory Copy(点对点内存复制)
Unified Virtual Address Space(统一虚拟地址空间)
Interprocess Communication(进程间通信)
Error Checking(错误检查)
Call Stack(调用堆栈)
Texture and Surface Memory
- Texture Memory
- Texture Object API
- Texture Reference API
- 16-Bit Floating-Point Textures
- Layered Textures
- Cubemap Textures
- Cubemap Layered Textures
- Texture Gather - Surface Memory
- Surface Object API
- Surface Reference API
- Cubemap Surfaces
- Cubemap Layered Surfaces - CUDA Arrays(CUDA Arrays)
- Read/Write Coherency(读/写一致性)
Graphics Interoperability(图形互操作性)
- OpenGL Interoperability
- Direct3D Interoperability
- Direct3D 9 Version
- Direct3D 10 Version
- Direct3D 11 Version - SLI Interoperability
External Resource Interoperability(外部资源互操作性)
Vulcan Interoperability(Vulcan互操作性)
- Matching device UUIDs(匹配设备的UUID)
- Importing memory objects(导入内存对象)
- Mapping buffers onto imported memory objects(将缓冲区映射到导入的内存对象)
- Mapping mipmapped arrays onto imported memory objects(将mipmapped数组映射到导入的内存对象)
- Importing synchronization objects(导入同步对象)
- Signaling/waiting on imported synchronization objects(Signaling/waiting 导入的同步对象)
OpenGL Interoperability(OpenGL互操作性)
Direct3D 12 Interoperability(Direct3D 12互操作性)
- Matching device LUIDs(匹配设备的LUID)
- Importing memory objects(导入内存对象)
- Mapping buffers onto imported memory objects(将缓冲区映射到导入的内存对象)
- Mapping mipmapped arrays onto imported memory objects(将mipmapped数组映射到导入的内存对象)
- Importing synchronization objects(导入同步对象)
- Signaling/waiting on imported synchronization objects(Signaling/waiting 导入的同步对象)
Direct3D 11 Interoperability(Direct3D 11互操作性)
- Matching device LUIDs(匹配设备的LUID)
- Importing memory objects(导入内存对象)
- Mapping buffers onto imported memory objects(将缓冲区映射到导入的内存对象)
- Mapping mipmapped arrays onto imported memory objects(将mipmapped数组映射到导入的内存对象)
- Importing synchronization objects(导入同步对象)
- Signaling/waiting on imported synchronization objects(Signaling/waiting 导入的同步对象)
NVIDIA Software Communication Interface Interoperability (NVSCI)(NVIDIA软件通信接口互操作性(NVSCI))
- Importing memory objects(导入内存对象)
- Mapping buffers onto imported memory objects(将缓冲区映射到导入的内存对象)
- Mapping mipmapped arrays onto imported memory objects(将mipmapped数组映射到导入的内存对象)
- Importing synchronization objects(导入同步对象)
- Signaling/waiting on imported synchronization objects(Signaling/waiting 导入的同步对象)