GPU和CUDA基础知识

GPU和CUDA基础

1.显卡、GPU、CUDA


显卡的作用

  • 将电脑的数字信号转换成模拟信号让显示器显示出来

独立显卡和集成显卡的区别

  • 所谓集成,是指显卡集成在主板上,不能随意更换。
  • 而独立显卡是作为一个独立的器件插在主板的接口上的,可以随时更换升级。
  • 集成显卡使用物理内存,而独立显卡有自己的显存。

NVIDIA显卡分类

  • GeForce系列:家庭娱乐
  • Quadro系列:专业绘图设计
  • Tesla系列:高端显卡,大规模并行运算

显卡和GPU的关系

  • GPU是显卡上的一块芯片。
  • 集成显卡和独立显卡都是有GPU的。

GPU的发展历程

  • 仅用于图形渲染,此功能是GPU的初衷
  • 后来人们发现,GPU这么一个强大的器件只用于图形处理太浪费了,它应该用来做更多的工作,例如浮点运算。怎么做呢?直接把浮点运算交给GPU是做不到的,因为它只能用于图形处理(那个时候)。最容易想到的,是把浮点运算做一些处理,包装成图形渲染任务,然后交给GPU来做。这就是 GPGPU(General Purpose GPU)的概念。不过这样做有一个缺点,就是你必须有一定的图形学知识,否则你不知道如何包装。
  • 于是,为了让不懂图形学知识的人也能体验到GPU运算的强大,Nvidia公司又提出了CUDA的概念。

CUDA

  • CUDA(Compute Unified Device Architecture),通用并行计算架构,是一种运算平台。它包含CUDA指令集架构以及GPU内部的并行计算引擎。你只要使用一种类似于C语言的 CUDA C语言,就可以开发CUDA程序,从而可以更加方便的利用GPU强大的计算能力,而不是像以前那样先将计算任务包装成图形渲染任务,再交由GPU处理。
  • 注意,并不是所有GPU都支持CUDA。

CPU和GPU

  • GPU是吞吐导向内核,CPU是延迟导向的内核
  • CPU擅长逻辑性强的运算,串行计算
  • GPU擅长高度线程化的并行处理任务

英伟达GPU架构

  • Tesla (特斯拉)
  • Fermi(费米)
  • Kepler(开普勒)
  • Maxwell(麦克斯韦)
  • Pascal(帕斯卡)
  • Volta(伏特)
  • Turing(图灵)
  • Ampere(安培)
  • Hopper(赫柏)

显存和内存

  • 显存是帮GPU存储的,内存是帮CPU存储的

GPU能与不能

  • GPU缓存小,不适合处理频繁访问内存的操作
  • GPU控制单元简单,不适合处理控制复杂的指令
  • GPU有大量的计算单元,适合计算密集型程序
  • GPU每一行的运算单元控制指令是一个,适合并行度高的程序

2.CUDA编程基础


CUDA并行计算流程

  • 申请显存 cudaMalloc
  • 转移拷贝 cudaMemcpy
    • Host --> Device
    • Device --> Host
  • 释放显存 cudaFree

CUDA硬件描述

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

CUDA内存模型

硬件名称 软件名称
线程处理器(SP) 线程(thread)
多核处理器(SM) 线程块(thread block)
设备端(device) 线程块组合体(grid)
  • 一个GPU有多个SM,这些SM有一个全局内存,所有的线程都可以访问
  • 每个SM都有一个共享内存,仅可以被线程块内的所有线程访问
  • 一个SM有多个SP,每个SP有一个局部内存,仅可以被该线程访问
  • 一个kernel由一个gird来执行,也就是一个kernel一次只能在一个GPU上执行
  • 一个线程块内的线程可以协作,不同线程块内的线程不能协作,线程块之间相互独立
  • 每个线程都有一个索引,用于计算内存地址

线程束

  • SM采用SIMT(Single-Instruction, Multiple-Thread, 单指令多线程)架构,线程束(warp)是最基本的执行单元
  • 线程束是指一个包含32个线程的集合,线程束中的每一个线程都将在不同的数据上执行相同的指令;(一个控制单元控制一行的计算单元,这些计算单元以不同的数据资源执行相同的指令)
  • 线程束本质上是线程在GPU上运行的最小单元
  • 线程块所包含的线程大小一般要设置为32的倍数

cudaEvent

    // 记录时间
    cudaEvent_t start, stop;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start, 0);

    // ...

    // 记录结束时刻
    cudaEventRecord(stop, 0);
    // 确保GPU执行完了前面的所有工作再读取stop时间
    // cudaEvent是在GPU上执行的,因此不适合对同时包含设备代码和主机代码的混合计时
    cudaEventSynchronize(stop);
    
    // // 计算时刻差
    float elapsedTime;
    cudaEventElapsedTime(&elapsedTime, start, stop);
    printf("Time of GPU: %3.1f ms\n", elapsedTime);
    cudaEventDestroy(start);
    cudaEventDestroy(stop);
  • cudaEventElapsedTime: 计算两个时间之间经历的时间
  • cudaEventDestroy: 使用完事件后要销毁事件(当做规定)

你可能感兴趣的:(模型部署,深度学习,人工智能)