> 文章列表 > cuda编程以及GPU基本知识

cuda编程以及GPU基本知识

cuda编程以及GPU基本知识

目录

    • CPU与GPU的基本知识
      • CPU特点
      • GPU特点
      • GPU vs. CPU
      • 什么样的问题适合GPU?
    • GPU编程
      • CUDA编程并行计算的整体流程
      • CUDA编程术语:硬件
      • CUDA编程术语:内存模型
      • CUDA编程术语:软件
      • 线程块(Thread Block)
      • 网格(grid)
      • 线程块id & 线程id
      • 线程束(warp)

CPU与GPU的基本知识

GPU:吞吐导向内核
CPU:延迟导向内核

  • 延迟:一条指令从发出到发出结果的时间间隔
  • 吞吐量:单位时间内处理指令的数量

CPU特点

  • 内存大:多级缓存结构提高访存速度
    • 处理运算速度远高于访问存储速度 -> 空间换时间
    • 经常访问的内容放到低级缓存(L1),不常访问的内容放到高级缓存
  • 控制复杂
    • 分支预测机制 (if-else/break/continue等 在硬件端的机制)
    • 流水线数据前送
  • 运算单元强大
    • 整型浮点型复杂运算速度快

请添加图片描述

GPU特点

  • 缓存小
    • 提高内存吞吐
  • 控制简单
    • 没有分支预测
    • 没有数据转发
    • (-> 复杂指令效率不高,简单指令吞吐显著提高)
  • 精简运算单元
    • 多长延时流水线以实现高吞吐量 (下图每一行绿色块)
    • 需要大量的线程来容忍延迟
      在这里插入图片描述
      如图中所示,每一行的运算单元只有一个控制器,所以每一行的运算单元执行的是同一个指令,只不过是使用不同的数据。

GPU vs. CPU

  • CPU:连续计算部分,延迟优先;相比GPU,单条指令延迟快十倍以上
  • GPU:并行计算部分,吞吐优先;相比CPU,单位时间内执行指令数量10倍以上

什么样的问题适合GPU?

  • 计算密集:数值计算比例远大于内存操作,因此内存访问的延时可以被计算覆盖
  • 数据并行:大任务可以拆解为相同指令的小人物,因此对复杂流程的控制需求较低

GPU编程

CUDA编程并行计算的整体流程

void GPUkernel(float* A, float* B, float* C, int n)
{
1. // Allocate device memory for A, B, and C// copy A and B to device memory2. // Kernel launch code – to have the device// to perform the actual vector addition3. // copy C from the device memory// Free device vectors
}

在这里插入图片描述

CUDA编程术语:硬件

  • Device = GPU
  • Host = CPU
  • Kernel = GPU上运行的函数

cuda编程以及GPU基本知识

CUDA编程术语:内存模型

CUDA中的内存模型分为一下几个层次:

  • 每个线程处理器 (Thread Processor, PS)都有自己的寄存器(register)
  • 每个SP都有自己的局部内存(local memory),register和local memory只能被线程自己访问
  • 每个多核处理器(SM)内都有自己的共享内存(shared memory),其可被线程块(Thread Block)内所有线程访问
  • 一个GPU的所有SM共有一块全局内存(global memory),不同线程块的线程都可以使用

CUDA编程术语:软件

  • 分为以下几个层次
    • 线程处理器(SP)对应线程(thread)
    • 多核处理器(SM)对应线程块(thred block)
    • 设备端(device)对应线程块组合体(grid)
  • 一个kernel其实由一个grid来执行
  • 一个kernel一次只能在一个GPU上执行请添加图片描述

线程块(Thread Block)

线程块:可扩展的集合体;将线程数组分成多个块

  • 块内的线程通过共享内存、原子操作和屏障同步进行协作(shared memory, atomic operations and barrier synchronization)
  • 不同块中的线程不能协作,即线程的操作是互相独立的互不影响的

在这里插入图片描述
如图,该线程块包含256个线程,所执行的任务为向量相加的操作。其中,i = … 为确定线程在显存中位置的计算公式。

网格(grid)

网格:并行线程块组合

  • CUDA核函数由线程网格(数组)执行
  • 每个线程都有一个索引,用于计算内存地址和做出决策控制
  • 每个线程块互不影响
  • 最后将N个线程块的结果进行融合
    cuda编程以及GPU基本知识

线程块id & 线程id

  • 每个线程要使用索引来决定要处理的数据
  • 无论是线程块id或是线程id,都可以是1维、2维或者3维的,如下图所示:

请添加图片描述

• dim3 dimGrid(M, N);
• dim3 dimBlock(P, Q, S);• threadId.x = blockIdx.x * blockDim.x + threadIdx.x;
• threadId.y = blockIdx.y * blockDim.y + threadIdx.y;

线程束(warp)

  • 多核处理器(SM)采用单指令多线程架构 SIMT(Single-Instruction, Multiple-Thread),其中warp(线程束)是最基本的执行单元,一个warp包含32个并行thread,这些thread以不同数据资源执行相同的指令。warp本质上是线程在GPU上运行的最小单元。
  • 当一个kernel被执行时,grid中的线程块被分配到SM上,一个线程块的thread只能在一个SM上调度,SM一般可以调度多个线程块,大量的thread可能被分到不同的SM上。每个线程拥有它自己的程序计数器和状态寄存器,并且用该线程自己的数据执行指令,这就是所谓的Single Instruction Multiple Thread(SIMT)。
  • 由于warp的大小为32,所以block所含的thread的大小一般要设置为32的倍数。(或者可以说,每个线程块要包含N个整行的计算单元,而不能是一半)

cuda编程以及GPU基本知识