Bootstrap

cuda基础教程(一)

0. CURA Runtime API

https://docs.nvidia.com/cuda/cuda-runtime-api/index.html

1. CUDA人工智能编程

1.1. CUDA介绍

  1. CUDA(Compute Unified Device Architecture)
  2. AI技术的繁荣和AI应用场景的逐渐丰富,AI模型的训练、大数据分析都对系统计算能力提出了更高的需求,CUDA平台都对此能够提供很好的计算支持
  3. 主流的AI框架如TensorFlow、Caffe、Pytorch都依赖于CUDA平台的强大计算能力来完成模型训练

1.2. 课程内容

  1. 开发环境搭建
  2. CUDA线程模型
  3. CUDA内存模型
  4. CUDA流和事件
  5. 底层指令优化
  6. CUDA调试

2. 异构计算和并行计算

2.1. 什么是并行计算

  • 任务并行,多个任务同时执行
  • 数据并行,多个数据同时被执行
    • 块分
    • 循环分块

2.2. 什么是异构计算

异构计算指在具有多种类型处理(CPU和GPU)的系统中完成的计算
在这里插入图片描述

GPU上进行并行计算(主要是数据并行)

3. CUDA介绍

3.1. GPU的性能指标

  1. GPU核心数(core number)
  2. GPU内存容量
  3. 计算峰值,每秒单精度或者双精度的运算能力
  4. 内存带宽,每秒读出或者写入GPU内存的数据量

3.2. 什么是CUDA

图形计算 -> 通用计算
在这里插入图片描述

  • CUDA C是对ANSI C的扩展

  • CUDA平台提供了驱动层接口(Driver API)和运行时接口(Runtime API)
    在这里插入图片描述

  • 基于CUPA平台开发的代码包含主机代码和设备代码

3.3. 如何学习CUDA

  1. CUDA C编程时只需要编写顺序执行的程序,在程序代码中不需要有多线程的处理
  2. 要深刻理解CUDA平台GPU的内存架构和线程架构
  3. 掌握CUDA平台常用的性能分析和调优工具
    1. NVIDIA Nsight
    2. CUDA-GDB
    3. 图形化性能分析工具

4. 系统GPU查询

  1. 系统GPU查询
lspci |grep nvidia

硬件是否支持CUDA查询: https://developer.nvidia.com/cuda-gpus

  1. GPU计算能力(compute capability)
    MajorVersion.MinorVersion

5. Linux系统

  • 系统版本
  • gcc
  • 内核头文件
sudo apt-get install linux-header-$(uname -r)

6. CUDA安装

安装完成后,验证

  1. 驱动版本
cat /proc/driver/nvidia/version
  1. nvcc编译器版本
nvcc -V

7. 查询GPU信息

  1. nvidia-smi 管理和检测GPU

8. CUDA编程模型

8.1. 什么是编程模型

  • 对底层计算机硬件架构的抽象表达
  • 编程模型作为应用程序和底层架构的桥梁
  • 编程模型体现在程序开发语言和开发平台中
    在这里插入图片描述

8.2. CUDA编程模型

  • CUDA平台对线程的管理
  • CUDA平台对内存访问控制
    • 主机内存和GPU设备内存
    • cpu和GPU之间内存数据传递
  • 内核函数(kernel function)
    • 内核代码本身不包含任何并行性,由gpu协调处理线程执行内核
    • CPU和GPU处于一步执行状态

9. CUDA线程模型

9.1. 线程模型结构

  1. 关键概念: grid(网格)和block(块)
    在这里插入图片描述

  2. 内核(kernel)执行时所产生的所有线程称为grid

  3. grid由多个block构成

  4. 相同block中的线程可以通过同步机制和块内共享内存做数据交互(不同的block之间无法数据交互)

9.2. 线程管理

  1. 线程标识
    1. blockIdx和threadIdx唯一标识每一个线程
    2. 线程标识由CUDA平台内置和分配,可以在内核程序中访问
    3. 两者均为三维向量, 访问方法blockIdx.x ,blockIdx.y, blockIdx.z, threadIdx.x,threadIdx.y,threadIdx.z
  2. 线程模型纬度(标识grid和block)
    1. 内置变量blockDim和gridDim
    2. 两者也是三维向量
  3. 线程ID(thread ID)和线程标识符换算关系

10. CUDA内存模型

10.1 内存架构

在这里插入图片描述

  1. 寄存器
    • GPU中访问最快的内存,为每个线程私有
  2. 本地内存
    • 无法存入寄存器的数据存于本地内存,如较大的数据结构
  3. 共享内存
    • 由__shared__修饰的变量都保存在共享内存中,是片上存储空间,具有低延迟和高带宽的特点
  4. 常量内存
    • 由__constant__修饰,可以被所有内核代码访问
  5. 全局内存
    • 数量大,使用最多,延迟最大
    • 静态分配:__device__关键字
    • 动态分配: 主机中使用内存管理函数
  6. 纹理内存

内存管理接口函数:
在这里插入图片描述

11. nvcc工作流程

11.1. nvcc是什么

  • 类似于gcc
  • nvcc将ptx或者c语言编写的代码编译为可执行程序

11.2. nvcc工作流程

  1. CUDA程序默认编译模式为全程序编译模式(主机代码和设备代码同时编译)
  2. 分离源文件和GPU相关的内核代码,编译为cubin或者PTX中间文件,保存在fatbinary中
  3. 分离源文件的主机代码,使用系统中可用的编译器(如gcc)进行编译,并将fatbinary嵌入其中
  4. 链接,相关的CUDA运行库会被链接
    在这里插入图片描述

nvcc入参文档:
https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html

12. CUDA内核函数

  • kernel function被GPU上线程并发执行

  • 内核函数定义

    • global void kernel_name(argument list)
  • CUDA程序中的函数修饰符(function qualifier)
    在这里插入图片描述

  • 内核函数限制条件:

    1. 只能访问GPU内存
    2. 必须返回void
    3. 不能使用变长参数
    4. 不能使用静态变量
    5. 不能使用函数指针
    6. 内核函数具有异步性
      Hello word内核函数
  1. code:
#inlcude <stdio.h>
__global__ void helloFromGPU()
{
    printf("Hello World From GPU\n");
}

int main()
{
    printf("Hello World From CPU\n");
    helloFromGPU<<<1,10>>>(); //会被10个线程执行
    cudaDeviceReset();
    return 0;
}
  1. 编译
nvcc helloFromGPU.cu --output-file helloGPU

13. 获取线程索引

  • 线程索引包含blockIdx和threadIdx
  • 通过线程索引可以为线程分配数据
  • 线程维度包含网格(grid)纬度gridDim、块(block)纬度blockDim定义
    示例代码:
#include "common/common.h"
#include <stdio.h>

__global__ void helloFromGPU()
{
    printf("blockDim:x=%d,y=%d,z=%d,gridDim:x=%d,y=%d,z=%d Current threadIdx:x=%d,y=%d,z=%d\n",blockDim.x,blockDim.y,blockDim.z,gridDim.x, gridDim.y, gridDim.z,threadIdx.x,threadIdx.y,threadIdx.z);
}

int main(int argc,char **argc)
{
    printf("Hello World from CPU!\n");
    dim3 grid;
    grid.x = 2;
    grid.y = 2;
    dim3 block;
    block.x = 2;
    block.y = 2;
    helloFromGPU<<<grid,block>>>();
    cudaDeviceReset();
    return 0;
}

14. CUDA错误处理

14.1. 错误代码

enum cudaError文档说明:
https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__TYPES.html

14.2. 错误处理函数

  • cudaGetErrorName(cudaError_t error)
  • cudaGetErrorString(cudaError_t errr)

15. 运行时GPU信息查询

文档:
https://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__DEVICE.html#group__CUDART__DEVICE_1g18808e54893cfcaafefeab31a73cc55f

  • 获取GPU数量:cudaGetDeviceCount
  • 设置需要使用的GPU: cudaSetDevice
  • 获取GPU信息: cudaGetDeviceProperties
;