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