GPU架构与计算入门指南

1比较CPU与GPU

首先,我们会比较CPU和GPU,这能帮助我们更好地了解GPU的发展状况,但这应该作为一个独立的主题,因为我们难以在一节中涵盖其所有的内容。因此,我们将着重介绍一些关键点。

CPU和GPU的主要区别在于它们的设计目标。CPU的设计初衷是执行顺序指令。一直以来,为提高顺序执行性能,CPU设计中引入了许多功能。其重点在于减少指令执行时延,使CPU能够尽可能快地执行一系列指令。这些功能包括指令流水线、乱序执行、预测执行和多级缓存等(此处仅列举部分)。

而GPU则专为大规模并行和高吞吐量而设计,但这种设计导致了中等至高程度的指令时延。这一设计方向受其在视频游戏、图形处理、数值计算以及现如今的深度学习中的广泛应用所影响,所有这些应用都需要以极高的速度执行大量线性代数和数值计算,因此人们倾注了大量精力以提升这些设备的吞吐量。

我们来思考一个具体的例子:由于指令时延较低,CPU在执行两个数字相加的操作时比GPU更快。在按顺序执行多个这样的计算时,CPU能够比GPU更快地完成。然而,当需要进行数百万甚至数十亿次这样的计算时,由于GPU具有强大的大规模并行能力,它将比CPU更快地完成这些计算任务。

我们可以通过具体数据来进行说明。硬件在数值计算方面的性能以每秒浮点运算次数(FLOPS)来衡量。NVIDIA的Ampere A100在32位精度下的吞吐量为19.5 TFLOPS。相比之下,Intel的24核处理器在32位精度下的吞吐量仅为0.66 TFLOPS(2021年)。同时,随时间推移,GPU与CPU在吞吐量性能上的差距逐年扩大。

CPU在芯片领域中主要用于降低指令时延的功能,例如大型缓存、较少的算术逻辑单元(ALU)和更多的控制单元。与此相比,GPU则利用大量的ALU来最大化计算能力和吞吐量,只使用极小的芯片面积用于缓存和控制单元,这些元件主要用于减少CPU时延。

时延容忍度和高吞吐量

或许你会好奇,GPU如何能够容忍高时延并同时提供高性能呢?GPU 拥有大量线程和强大的计算能力,使这一点成为可能。即使单个指令具有高延迟,GPU 也会有效地调度线程运行,以便它们在任意时间点都能利用计算能力。例如,当某些线程正在等待指令结果时,GPU 将切换到运行其他非等待线程。这可确保 GPU 上的计算单元在所有时间点都以其最大容量运行,从而提供高吞吐量。稍后当我们讨论kernel如何在 GPU 上运行时,我们将对此有更清晰的了解。

GPU架构

我们已经了解到GPU有利于实现高吞吐量,但它们是通过怎样的架构来实现这一目标的呢?本节将对此展开探讨。

GPU的计算架构

GPU由一系列流式多处理器(SM)组成,其中每个SM又由多个流式处理器、核心或线程组成。例如,NVIDIA H100 GPU具有132个SM,每个SM拥有64个核心,总计核心高达8448个。

每个SM都拥有一定数量的片上内存(on-chip memory),通常称为共享内存或临时存储器,这些共享内存被所有的核心所共享。同样,SM上的控制单元资源也被所有的核心所共享。此外,每个SM都配备了基于硬件的线程调度器,用于执行线程。

除此之外,每个SM还配备了几个功能单元或其他加速计算单元,例如张量核心(tensor core)或光线追踪单元(ray tracing unit),用于满足GPU所处理的工作负载的特定计算需求。

接下来,让我们深入剖析GPU内存并了解其中的细节。

GPU的内存架构

让我们对其进行剖析:

  • 寄存器:让我们从寄存器开始。GPU中的每个SM都拥有大量寄存器。例如,NVIDIA的A100和H100模型中,每个SM拥有65536个寄存器。这些寄存器在核心之间共享,并根据线程需求动态分配。在执行过程中,每个线程都被分配了私有寄存器,其他线程无法读取或写入这些寄存器。
  • 常量缓存:接下来是芯片上的常量缓存。这些缓存用于缓存SM上执行的代码中使用的常量数据。为利用这些缓存,程序员需要在代码中明确将对象声明为常量,以便GPU可以将其缓存并保存在常量缓存中。
  • 共享内存:每个SM还拥有一块共享内存或临时内存,它是一种小型、快速且低时延的片上可编程SRAM内存,供运行在SM上的线程块共享使用。共享内存的设计思路是,如果多个线程需要处理相同的数据,只需要其中一个线程从全局内存(global memory)加载,而其他线程将共享这一数据。合理使用共享内存可以减少从全局内存加载重复数据的操作,并提高内核执行性能。共享内存还可以用作线程块(block)内的线程之间的同步机制。
  • L1缓存:每个SM还拥有一个L1缓存,它可以缓存从L2缓存中频繁访问的数据。
  • L2缓存:所有SM都共享一个L2缓存,它用于缓存全局内存中被频繁访问的数据,以降低时延。需要注意的是,L1和L2缓存对于SM来说是公开的,也就是说,SM并不知道它是从L1还是L2中获取数据。SM从全局内存中获取数据,这类似于CPU中L1/L2/L3缓存的工作方式。
  • 全局内存:GPU还拥有一个片外全局内存,它是一种容量大且带宽高的动态随机存取存储器(DRAM)。例如,NVIDIA H100拥有80 GB高带宽内存(HBM),带宽达每秒3000 GB。由于与SM相距较远,全局内存的时延相当高。然而,芯片上还有几个额外的存储层以及大量的计算单元有助于掩饰这种时延。

现在我们已经了解GPU硬件的关键组成部分,接下来我们深入一步,了解执行代码时这些组件是如何发挥作用的。

了解GPU的执行模型

要理解GPU如何执行kernel,我们首先需要了解什么是kernel及其配置。

CUDA Kernel与线程块简介

CUDA是NVIDIA提供的编程接口,用于编写运行在其GPU上的程序。在CUDA中,你会以类似于C/C++函数的形式来表达想要在GPU上运行的计算,这个函数被称为kernel。kernel在并行中操作向量形式的数字,这些数字以函数参数的形式提供给它。一个简单的例子是执行向量加法的kernel,即接受两个向量作为输入,逐元素相加,并将结果写入第三个向量。

要在GPU上执行kernel,我们需要启用多个线程,这些线程总体上被称为一个网格(grid),但网格还具有更多的结构。一个网格由一个或多个线程块(有时简称为块)组成,而每个线程块又由一个或多个线程组成。

线程块和线程的数量取决于数据的大小和我们所需的并行度。例如,在向量相加的示例中,如果我们要对256维的向量进行相加运算,那么可以配置一个包含256个线程的单个线程块,这样每个线程就可以处理向量的一个元素。如果数据更大,GPU上也许没有足够的线程可用,这时我们可能需要每个线程能够处理多个数据点。

编写一个kernel需要两步。第一步是运行在CPU上的主机代码,这部分代码用于加载数据,为GPU分配内存,并使用配置的线程网格启动kernel;第二步是编写在GPU上执行的设备(GPU)代码。

由于本文的重点不在于教授CUDA,因此我们不会更深入地讨论此段代码。现在,让我们看看在GPU上执行kernel的具体步骤。

在GPU上执行Kernel的步骤

1.将数据从主机复制到设备

在调度执行kernel之前,必须将其所需的全部数据从主机(即CPU)内存复制到GPU的全局内存(即设备内存)。尽管如此,在最新的GPU硬件中,我们还可以使用统一虚拟内存直接从主机内存中读取数据(可参阅论文《EMOGI: Efficient Memory-access for Out-of-memory Graph-traversal in GPUs》)。

2. SM上线程块的调度

当GPU的内存中拥有全部所需的数据后,它会将线程块分配给SM。同一个块内的所有线程将同时由同一个SM进行处理。为此,GPU必须在开始执行线程之前在SM上为这些线程预留资源。在实际操作中,可以将多个线程块分配给同一个SM以实现并行执行。

由于SM的数量有限,而大型kernel可能包含大量线程块,因此并非所有线程块都可以立即分配执行。GPU会维护一个待分配和执行的线程块列表,当有任何一个线程块执行完成时,GPU会从该列表中选择一个线程块执行。

3. 单指令多线程 (SIMT) 和线程束(Warp)

众所周知,一个块(block)中的所有线程都会被分配到同一个SM上。但在此之后,线程还会进一步划分为大小为32的组(称为warp),并一起分配到一个称为处理块(processing block)的核心集合上进行执行。

SM通过获取并向所有线程发出相同的指令,以同时执行warp中的所有线程。然后这些线程将在数据的不同部分,同时执行该指令。在向量相加的示例中,一个warp中的所有线程可能都在执行相加指令,但它们会在向量的不同索引上进行操作。

由于多个线程同时执行相同的指令,这种warp的执行模型也称为单指令多线程 (SIMT)。这类似于CPU中的单指令多数据(SIMD)指令。

Volta及其之后的新一代GPU引入了一种替代指令调度的机制,称为独立线程调度(Independent Thread Scheduling)。它允许线程之间完全并发,不受warp的限制。独立线程调度可以更好地利用执行资源,也可以作为线程之间的同步机制。本文不会涉及独立线程调度的相关内容,但你可以在CUDA编程指南中了解更多相关信息。

4. Warp调度和时延容忍度

关于warp的运行原理,有一些值得讨论的有趣之处。

即使SM内的所有处理块(核心组)都在处理warp,但在任何给定时刻,只有其中少数块正在积极执行指令。因为SM中可用的执行单元数量是有限的。

有些指令的执行时间较长,这会导致warp需要等待指令结果。在这种情况下,SM会将处于等待状态的warp休眠,并执行另一个不需要等待任何结果的warp。这使得GPU能够最大限度地利用所有可用计算资源,并提高吞吐量。

零计算开销调度:由于每个warp中的每个线程都有自己的一组寄存器,因此SM从执行一个warp切换到另一个warp时没有额外计算开销。

与CPU上进程之间的上下文切换方式(context-switching)不同。如果一个进程需要等待一个长时间运行的操作,CPU在此期间会在该核心上调度执行另一个进程。然而,在CPU中进行上下文切换的代价昂贵,这是因为CPU需要将寄存器状态保存到主内存中,并恢复另一个进程的状态。

5. 将结果数据从设备复制到主机内存

最后,当kernel的所有线程都执行完毕后,最后一步就是将结果复制回主机内存。

尽管我们涵盖了有关典型kernel执行的全部内容,但还有一点值得讨论:动态资源分区。

资源划分和占用概念

我们通过一个称为“occupancy(占用率)”的指标来衡量GPU资源的利用率,它表示分配给SM的warp数量与SM所能支持的最大warp数量之间的比值。为实现最大吞吐量,我们希望拥有100%的占用率。然而,在实践中,由于各种约束条件,这并不容易实现。

为什么我们无法始终达到100%的占用率呢?SM拥有一组固定的执行资源,包括寄存器、共享内存、线程块槽和线程槽。这些资源根据需求和GPU的限制在线程之间进行动态划分。例如,在NVIDIA H100上,每个SM可以处理32个线程块、64个warp(即2048个线程),每个线程块拥有1024个线程。如果我们启动一个包含1024个线程的网格,GPU将把2048个可用线程槽划分为2个线程块。

动态分区vs固定分区:动态分区能够更为有效地利用GPU的计算资源。相比之下,固定分区为每个线程块分配了固定数量的执行资源,这种方式并不总是最有效的。在某些情况下,固定分区可能会导致线程被分配多于其实际需求的资源,造成资源浪费和吞吐量降低。

下面我们通过一个例子说明资源分配对SM占用率的影响。假设我们使用32个线程的线程块,并需要总共2048个线程,那么我们将需要64个这样的线程块。然而,每个SM一次只能处理32个线程块。因此,即使一个SM可以运行2048个线程,但它一次也只能同时运行1024个线程,占用率仅为50%。

同样地,每个SM具有65536个寄存器。要同时执行2048个线程,每个线程最多有32个寄存器(65536/2048 =32)。如果一个kernel需要每个线程有64个寄存器,那么每个SM只能运行1024个线程,占用率同样为50%。

占用率不足的挑战在于,可能无法提供足够的时延容忍度或所需的计算吞吐量,以达到硬件的最佳性能。

高效创建GPU kernel是一项复杂任务。我们必须合理分配资源,在保持高占用率的同时尽量降低时延。例如,拥有大量寄存器可以加快代码的运行速度,但可能会降低占用率,因此谨慎优化代码至关重要。

总结

我理解众多的新术语和新概念可能令读者望而生畏,因此文章最后对要点进行了总结,以便快速回顾。

  • GPU由多个SM组成,每个SM又包含多个处理核心。
  • GPU上存在着一个片外全局内存,通常是高带宽内存(HBM)或动态随机存取内存(DRAM)。它与芯片上的SM相距较远,因此时延较高。
  • GPU中有两个级别的缓存:片外L2缓存和片上L1缓存。L1和L2缓存的工作方式类似于CPU中的L1/L2缓存。
  • 每个SM上都有一小块可配置的共享内存。这块共享内存在处理核心之间共享。通常情况下,线程块内的线程会将一段数据加载到共享内存中,并在需要时重复使用,而不是每次再从全局内存中加载。
  • 每个SM都有大量寄存器,寄存器会根据线程需求进行划分。NVIDIA H100每个SM有65536个寄存器。
  • 在GPU上执行kernel时,我们需要启动一个线程网格。网格由一个或多个线程块组成,而每个线程块又由一个或多个线程组成。
  • 根据资源可用性,GPU会分配一个或多个线程块在SM上执行。同一个线程块中的所有线程都会被分配到同一个SM上执行。这样做的目的是为了充分利用数据的局部性(data locality),并实现线程之间的同步。
  • 被分配给SM的线程进一步分为大小为32的组,称为warp。一个warp内的所有线程同时执行相同的指令,但在数据的不同部分上执行(SIMT)(尽管新一代GPU也支持独立的线程调度)。
  • GPU根据每个线程的需求和SM的限制,在线程之间进行动态资源划分。程序员需要仔细优化代码,以确保在执行过程中达到最高的SM占用率。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/137946.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AIGC视频生成/编辑技术调研报告

人物AIGC:FaceChain人物写真生成工业级开源项目,欢迎上github体验。 简介: 随着图像生成领域的研究飞速发展,基于diffusion的生成式模型取得效果上的大突破。在图像生成/编辑产品大爆发的今天,视频生成/编辑技术也引起…

vscode 无法激活conda虚拟环境

vscode 无法激活conda虚拟环境 今天装odoo17的过程中,指定了conda虚拟环境,打开终端的时候无法激活 PS C:\Users\Administrator> conda activate py311 usage: conda-script.py [-h] [--no-plugins] [-V] COMMAND ... conda-script.py: error: argu…

Milvus Cloud——LLM Agent 现阶段出现的问题

LLM Agent 现阶段出现的问题 由于一些 LLM(GPT-4)带来了惊人的自然语言理解和生成能力,并且能处理非常复杂的任务,一度让 LLM Agent 成为满足人们对科幻电影所有憧憬的最终答案。但是在实际使用过程中,大家逐渐发现了通…

conda环境中pytorch1.2.0版本安装包安装一直失败解决办法!!!

conda环境中pytorch1.2.0版本安装包安装一直失败解决办法 cuda10.0以及cudnn7.4现在以及安装完成,就差torch的安装了,现在torch我要装的是1.2.0版本的,安装包以及下载好了,安装包都是在这个网站里下载的(点此进入&…

什么是 CSRF 攻击?如何防止 CSRF 攻击?

CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的网络安全攻击方式,攻击者利用用户已经通过认证的身份在受信任网站上执行未经用户授权的操作。 CSRF 攻击的一般过程如下: 用户登录受信任网站 A&#xff…

Kali常用配置(持续更新)

1. 同步系统时间 命令:dpkg-reconfigure tzdata ,这个命令可以同时更新系统时间和硬件时间。 然后选择区域和城市,中国可以先选择Asia,然后选择Shanghai 2.更换系统数据源 # vim /etc/apt/sources.list #不是root用户的话需要…

Linux学习-破解Root密码

破解root密码思路 1)重启系统,进入 救援模式 开启虚拟机A,在此界面按e键 在linux开头的该行,将此行的ro修改为rw 然后空格输入 rd.break 按 ctrl x 启动,会看到switch_root:/# 2)切换到硬盘操作系统环境 # chroot …

ChatGPT和API发生重大中断!

11月9日凌晨,OpenAI在官网发布,ChatGPT和API发生重大中断,导致全球所有用户无法正常使用,宕机时间超过2小时。 目前,OpenAI已经找到问题所在并进行了修复,但仍然不稳定,会继续进行安全监控。 …

asp.net core mvc之 视图

一、在控制器中找到匹配视图,然后渲染成 HTML 代码返回给用户 public class HomeController : Controller {public IActionResult Index(){return View(); //默认找 Views/Home/Index.cshtml ,呈现给用户} } 二、指定视图 1、控制器 publ…

QML10、QML 和 C++ 集成概述

概述 - QML 和 C++ 集成 QML 旨在通过 C++ 代码轻松扩展。 Qt QML 模块中的类允许从 C++ 加载和操作 QML 对象,并且 QML 引擎与 Qt 元对象系统集成的特性使 C++ 功能可以直接从 QML 调用。 这允许开发使用 QML、JavaScript 和 C++ 代码混合实现的混合应用程序。 集成 QML 和 C…

『 Linux 』进程概念

文章目录 🗞️ 冯诺依曼体系结构 🗞️📃 为什么在计算机当中需要使用内存充当中间介质而不使CUP与外设直接进行交互?📃 CPU如何读取数据 🗞️ 操作系统(Operating system) 🗞️📃 操作系统如何…

使用JavaScript编写游戏平台数据爬虫程序

目录 一、引言 二、准备工作 三、爬取数据 四、数据处理与存储 五、数据分析与利用 六、结论与展望 一、引言 随着网络技术的发展,数据已经成为企业、研究机构和个人的重要资源。数据可以帮助我们了解市场趋势、用户需求,甚至可以用于机器学习和人…

【23种设计模式】单一职责原则

个人主页:金鳞踏雨 个人简介:大家好,我是金鳞,一个初出茅庐的Java小白 目前状况:22届普通本科毕业生,几经波折了,现在任职于一家国内大型知名日化公司,从事Java开发工作 我的博客&am…

100+ Windows运行命令大全,装B高手必备

操作电脑关闭、重启、注销、休眠的命令细则: 用法: shutdown [/i | /l | /s | /sg | /r | /g | /a | /p | /h | /e | /o] [/hybrid] [/soft] [/fw] [/f] [/m \\computer][/t xxx][/d [p|u:]xx:yy [/c "comment"]] 没有参数 显示帮助。这与键入 /? 是一样的。…

基于SpringBoot+Redis的前后端分离外卖项目-苍穹外卖(三)

员工分页查询和账号启用禁用功能 1. 员工分页查询1.1 需求分析和设计1.1.1 产品原型1.1.2 接口设计 1.2 代码开发1.2.1 设计DTO类1.2.2 封装PageResult1.2.3 Controller层1.2.4 Service层接口1.2.5 Service层实现类1.2.6 Mapper层 1.3 功能测试1.4 代码完善 2. 启用禁用员工账号…

顶顶通语音识别使用说明

介绍 顶顶通语音识别软件(asrproxy)是一个对接了多种语音识别接口的语音识别系统。可私有化部署(支持中文英文和方言等,支持一句话识别、实时流识别、多声道录音文件识别。 原理 asrproxy内嵌了阿里达摩院的开源语音识别工具包FunASR,后续我们也会使用自有的预料…

【科研绘图】MacOS上的LaTeX公式插入工具——LaTeXiT

在Mac上经常用OmniGraffle绘图,但是有个致命缺点是没办法插入LaTeX公式,很头疼。之前有尝试用Pages文稿插入公式,但是调字体和颜色很麻烦。并且,PPT中的公式插入感觉也不太好看。 偶然机会了解到了LaTeXiT这个工具,可…

thinkphp6 起步

1、安装 composer create-project topthink/think6.0 tp62、使用多应用模式,你需要安装多应用模式扩展think-multi-app composer require topthink/think-multi-app3、config/app.php中,将 ‘auto_multi_app’ > flase, 改为true; 需要自…

QRadioButton、QCheckBox样式表

QRadioButton、QCheckBox样式表 实现效果Chapter1 QRadioButton样式表详细描述示例效果源码样式表 Chapter2 QRadioButton样式表 实现效果 QRadioButton{spacing: 2px;color: white; } QRadioButton::indicator {width: 60px;height: 35px; } QRadioButton::indicator:unchecke…

赛宁网安入选国家工业信息安全漏洞库(CICSVD)2023年度技术组成员单

近日,由国家工业信息安全发展研究中心、工业信息安全产业发展联盟主办的“2023工业信息安全大会”在北京成功举行。 会上,国家工业信息安全发展研究中心对为国家工业信息安全漏洞库(CICSVD)提供技术支持的单位授牌表彰。北京赛宁…