CUDA
第一章 CUDA基础
自学视频学习笔记
一、CUDA
CUDA(Compute Unified Device Architecture)—Nvidia推出的计算平台,在此平台上可使用GPU解决复杂的计算问题。基于GPU的通用高性能计算平台和编程模型。
二、CUAD开发环境搭建
软硬件需求
- 硬件需求:支持CUDA平台的GPU,算力在5.0以上
- 软件需求:Linux 16.04LTS,CUDA10.01
三、CUAD基础理论知识
1.并行计算和异构计算
并行计算和异构计算都属于高性能计算
1.1并行计算(parallel computing)
并行计算是一种计算形式,将大问题拆分成许多可以并发执行的小问题。并行计算可分为:任务并行(task parallel)和数据并行(data parallel)
- 任务并行是指多个任务同时执行
- 数据并行指多个数据同时被处理,每个数据由独立线程处理
- 数据并行分块方法:块分(block partitioning)和循环分块(cyclic partitioning)
1.2异构计算(heterogeneous computing)
异构计算指的是在具有多种类型处理器(CPU和GPU)系统中完成的计算。CPU更擅长逻辑处理,GPU更删除数据处理。
CPU | GPU |
---|---|
准备开始计算 | |
准备所需数据 | 接受数据 |
发出计算指令 | 执行计算 |
等待计算完成 | |
接受结果 | 返回结果 |
GPU和CPU之间总是异步的,GPU上有所谓的指令流水线,可以缓存接受到的任务并逐个执行。CPU无需等待GPU执行结果就可以继续他的工作内容。由于硬件特性以及设备流水线的存在。神经网络延迟和吞吐量并不成反比。即:latency不等于1/Thoughput
- latency为执行某个操作或者传输数据所需时间。
- Thoughput是指在给定时间系统可以处理的任务或者操作数量。
如果是选择自动驾驶这种实时性强的任务,则要注重低延迟,如果是推荐系统这种部署在服务器的项目则要注重吞吐量。
2.GPU性能指标
CUDA是软件平台必须配合硬件GPU才能做高性能计算
- GPU核心数(core number)
- GPU内存容量
- 计算峰值(每秒钟单精度或双精度运算能力)
- 内存带宽(每秒读出或者写入GPU内存的数据量)
3.CUDA软件架构
基于CUDA平台开发的程序包含主机代码和设备代码。CUDA C 编程时只需要编写顺序执行程序,在程序代码中不需要有多线程处理。
CUDA软件架构图
CUDA平台提供了驱动层接口(Driver API)和运行时接口(Runtime API)
- CUDA Driver API 直接是对GPU硬件进行编程;
- 基于Runtime API 可以开发CUDA Libraries ;
- 在CUDA库上面可以开发应用程序。
4.系统GPU检测
4.1系统GPU确认
nvidia-smi --query-gpu=gpu_name --format=csv,noheader
nvidia-smi -q #查询GPU具体信息
4.2 linux版本检测
uname -rm && cat /etc/*release
4.2 gcc 版本检测
gcc --version
4.3 检查系统内核头文件和开发工具包
uname -r #输出内核头文件版本
sudo apt-get install linux-headers-$(uname -r)
#如果无法安装执行
sudo apt-get update
sudo apt-get install linux-headers-$(uname -r)
三、CUAD模型
1.CUDA编程模型
编程模型是对底层计算机硬件架构的抽象表达,作为应用程序和底层架构的桥梁。
Applications |
---|
Programming Model |
Complier/Library(Communication Abstraction) |
Operating System(User/System Boundary) |
Architectures(Hardware/Software Boundary) |
CUDA平台对线程的管理
- 提供了线程抽象接口控制GPU中线程
CUDA平台对内存的访问控制
- 主机内存和GPU内存
- CPU和GPU之间内存数据传递
内核函数(kernel function)
-
内核代码本身不包含任何并行性,由GPU协调处理线程执行内核
-
CPU和GPU处于异步执行状态
2.CUDA线程模型
2.1 grid(网格)和block(块)
kernel执行时所产生的所有线程称为grid,每一次Kernel执行就会产生与之对应的grid,线程就在grid里面执行。
grid由多个block构成,每个block包含很多Thread,相同的block中的线程可以通过同步机制和块内共享内存做数据交互,不同的block线程之间不能进行数据交换。
2.2 线程管理
2.2.1线程标识
每一个线程是由blockIdx和threadIdx唯一标识。线程标识是CUDA平台内置和分配,并且可以在内核程序中进行访问,不能在主机代码中访问。线程标识(blockIdx、threadIdx)是三维向量,通过下标x,y,z访问
2.2.2线程模型维度
线程模型维度由内置变量blockDim和gridDim标识
2.2.3线程ID(thread ID)
线程ID(thread ID)和线程标识符换算关系:如果block维度是(Dx ,Dy) 线程标识为(i,j) thread ID =(i+j*Dx)
3.CUDA内存模型
3.1内存架构
GPU有多种不同用途的内存
GPU具有多种不同用途的内存:
- 寄存器(Register)
- 全局内存(global memory)
- 共享内存(shared memory)
- 线程私有内存(thread private local memory)
- 常量内存(constant memory)
- 纹理内存(texture memory)
如图 线程块中的共享内存可以被所有内存所共享,同一个线程块中的线程可通过共享内存进行数据交换。每一个Thread都可以访问自己的Registers,不能访问其他线程的寄存器,寄存器内存是线程所独有的。
Local Memory也是线程所独有的。Global Memory、constant memory 、texture memory都是用于线程与主机的交换,所有线程共享。
3.2内存管理
CUDA内存管理包含GPU内存分配,释放,数据在主机和设备间的传递
STANDARD C FUNCTIONS | CUDA C FUNCTIONS |
---|---|
malloc(内存分配) | cudaMalloc |
memcpy(内存数据复制) | cudaMemcpy |
memset(内存设置) | cudaMemset |
free(内存释放) | cudaFree |
3.2.1 寄存器
GPU中访问速度最快的内存,内核代码中声明的没有其他任何修饰符的自动变量通常放在寄存器中。寄存器内存是每个线程私有,用于存放经常访问的变量。
3.2.2 本地内存
内核函数中无法存放到寄存器中的变量会被存放到本地内存中,比如在编码译码是无法确定下标的数组,较大的数据结构,不满足内核寄存器限制条件的变量。
3.2.3 共享内存
内核函数中由__shared__修饰的变量都保存在共享内存中,共享是片上存储空间(on-clip),具有低延迟和高带宽特点。
3.2.4 常量内存
由__constant__修饰的变量存放在常量内存中,常量内存可以被所有内核代码访问
3.2.5 全局内存
全局内存数量最大,使用最多,延迟最大
静态分配:__device__关键字
动态分配:主机中使用内存管理函数
总结
CUDA为专题内容,后续会继续补充。