CUDA官方文档转接
一、简介
- GPU将更多晶体管用于数据计算,而CPU将更多晶体管用于流管理。
- GPU通过用计算掩盖访存延迟,而CPU采用大容量的cache和复杂的流处理。
1.1 可扩展编程模型
-
利用多核处理器如GPU的编程面临的问题是:如何透明地利用日益增长的核数。
-
cuda提供了一个简单的编程模型,而又能解决上述问题的方法。
核心分为三个关键抽象:
- 线程组织层级结构。
- 共享内存。
- 阻碍同步。
保留了线程协作的表达性,但是提供了自动扩展的能力。
-
线程block可以放到任何SM上运行。
图1. 自动扩展性
block间执行的隔离性使得 每个block并不在乎在哪个SM上运行,所以当硬件SM数量比较多时,可以同时运行多个block,当SM数量较小时,block之间可以排队等待在一个SM上运行。自动扩展性的由来。
二、CUDA编程模型
2.1 kernel
2.2 线程层级结构
2.3 memory hierarchy
2.4 异构编程
三、编程接口
3.1编译模型
3.1.1 编译工作流–离线编译
-
分离主机代码和设备代码。
-
将设备代码编译成汇编格式(PTX code)或二进制格式(cubin object)。
-
修改主机代码,将
<<<...>>>
语法替换成必要的CUDA runtime function calls。来启动 PTX格式代码或者cubin object。 -
剩下的C++代码要么交给其他要么交给nvcc去编译。
3.1.2 编译工作流–即时编译
- 系统运行时加载PTX code。
- 被driver编译成二进制文件。
- 通过**CUDA Environment Variables**可以控制CUDA编译时的操作。
3.2 CUDA运行时
在cudart库中实现,要么通过cudart.lib
、libcudart.a
或者cudart.dll
或libcudart.so
。
连接到同一个cuda runtime instance的组件之间传递cuda runtime symbol的地址才是安全的。
3.2.1 CUDA Runtime初始化
-
cuda runtime没有显式的初始化函数,当调用第一个runtime函数时才会初始化一个runtime instance。
-
runtime为系统中每个设备创建一个上下文(context)。
- 这一个context被称为primary context:在第一次调用需要active context的接口时创建。
- 此应用上所有线程共享此primary context。
- 创建primary context时,如果必要,device code被JIT编译,然后上传至device memory。
-
以上操作是透明的,如果需要,可以通过driver API获得。
-
当线程调用
cudaDeviceReset()
时,它将销毁它current work on的primary context。- 任何线程再在此设备上调用runtime function时会重新创建一个primary context。
-
CUDA interface使用global state:<