通用图形处理器设计GPGPU基础与架构(二)
一、前言
本系列旨在介绍通用图形处理器设计GPGPU的基础与架构,因此在介绍GPGPU具体架构之前,需要了解GPGPU的编程模型,了解软件层面是怎么做到并行的,硬件层面又要怎么配合软件,乃至定出合适的架构来实现软硬件协同。
二、通用编程背景
为了满足人们对GPU进行通用编程的需求,NVIDIA 公司于2007年发布了CUDA(Compute Unified Device Architecture,计算统一设备体系结构),支持编程人员利用更为通用的方式对GPU进行编程,更好地发挥底层硬件强大的计算能力,从而高效地解决各领域中的计算问题和任务。随后,苹果、AMD和 IBM 等公司也推出了OpenCL(Open Computing Language,开放运算语言)标准。该标准成为第一个面向异构系统通用并行编程的免费标准,适用于多核CPU 、GPGPU等多种异构并行系统。
三、GPGPU计算模型
本主要以CUDA并行编程中的一些架构概念来展示GPGPU的计算和存储模型。作为首个GPGPU编程模型,CUDA 定义了以主从方式结合单指令多线程(Single Instruction Multiple Threads,SIMT)硬件的多线程计算方式。

以上图的矩阵乘法为例,矩阵C中每个元素都可以由一个输入矩阵A的行向量和另一个输入矩阵B的列向量进行点积运算得到。C中每个元素的计算过程都可以独立进行,不存在依赖关系,因此具有良好的数据并行性。
在GPGPU中,承担并行计算中每个计算任务的计算单元称为线程(Thread),每个线程在一次计算任务过程中会执行相同的指令。在上例矩阵乘法中,每个线程会从矩阵A和B读取对应的行或列构成向量a和b, 然后执行向量点积运算,最后将结果c存到结果矩阵C的对应位置。
虽然每个线程输入数据不同,输出的结果也不同,但是每个线程需要执行的指令完全相同。也就是说, 一条指令被多个线程同时执行,这就是GPGPU 中的单指令多线程(Single Instruction Multiple Threads,SIMT)计算模型。
为了针对复杂的大规模通用计算场景将不方便处理,CUDA 引入了线程网格(thread grid)、线程块(thread block)、线程(thread)。Thread Block由多个Thread组成,而Grid又由多个Thread Block组成。因此,它们的关系就是Grid > Block > Thread。
在CUDA编程模型中,通常将代码划分为主机端(host)代码和设备端(device)代码,分别运行在CPU和GPGPU上。CPU硬件执行主机端代码,GPGPU硬件将根据编程人员给定的线程网格组织方式将设备端代码分发到线程中。
主机端代码通常分为三个步骤。①数据复制:CPU将主存中的数据复制到GPGPU中。②GPGPU启动:CPU 唤醒GPGPU线程进行运算。③数据写回:GPGPU运算完毕将计算结果写回主机端存储器中。
设备端代码常常由多个函数组成,这些函数被称为内核函数(kernel)。内核函数会被分配到每个GPGPU的线程中执行,而线程层次则由编程人员根据算法和数据的维度显式指定,如下图所示。

基于上面的线程层次,编程人员需要知道线程在网格中的具体位置,才能读取合适的数据执行相应的计算。因此,CUDA引入了为每个线程指明其在线程网格中哪个线程块的 blockIdx(线程块索引号)和线程块中哪个位置的threadIdx(线程索引号)。blockIdx有三个属性,x、y、z描述了该线程块所处线程网格结构中的位置。threadIdx 也有三个属性,x、y、z 描述了每个线程所处线程块中的位置。在一个Grid中:根据blockIdx和threadIdx,我们就能唯一锁定到某个线程,进而编程让其做具体计算。例如下面这段代码,调用线程进行了矩阵加法。
// Kernel定义
__global__ void MatAdd(float A[N][N], float B[N][N], float C[N][N])
{ int i = blockIdx.x * blockDim.x + threadIdx.x; int j = blockIdx.y * blockDim.y + threadIdx.y; if (i < N && j < N) C[i][j] = A[i][j] + B[i][j];
}
矩阵加法计算时,数据之间没有依赖性,每个线程都是并行独立地操作数据。
到此,可能会有个疑问,既然通用计算追根到底是索引到单个thread再做计算,那么假设没有block,我纯靠threadidx也能唯一索引到某个线程,block存在的意义到底是什么?。这就要引入共享存储器和全局存储器的概念了
首先,共享存储器的访问比全局存储器更快,共享存储器作用于一个线程块(thread block)内部,可以为同一个线程块内部的线程提供更快的数据访问。因此,通过合理划分块(block)的大小,可以充分利用数据的局部性原理减少对设备端全局存储器的访问,从而提高运算性能。此外,线程之间由于应用的特点可能不能完全独立。比如归约(reduction)操作需要邻近的线程之间频繁地交互数据,以协作的方式产生最终的结果,多个线程之间还可能需要相互同步,block的存在提高了线程之间的协作能力。
四、自线程到硬件结构
为了实现对大量线程的分配,GPGPU 对硬件功能单元进行了层次化的组织,如图所示。

它主要由流多处理器(Streaming MultiProcessor,SM)阵列和存储系统组成,两者由片上网络连接到L2高速缓存和设备端存储器上。每个流多处理器内部有多个流处理器(Streaming Processor,SP)单元,构成一套完整的指令流水线,包含取指、译码、寄存器文件及数据加载/存储(load/store)单元等,并以SIMT 架构的方式进行组织。GPGPU的整体结构、SM 硬件 和SP 硬件对应了线程网格、线程块和线程的概念,实现了线程到硬件的对应分配规则。
五、存储模型
GPGPU利用大量的线程来提高运算的并行度,这些线程需要到全局存储器中索引相应的数据。为了减少对全局存储器的访问,GPGPU架构提供了多种存储器类型和多样的存储层次关系来提高kernel函数的执行效率,如下表所示。
| Memory Description | CUDA Memory Name |
| 所有的线程(或所有work-items)均可访问 | global memory |
| 只读存储器 | constant memory |
| 线程块(或work-group)内部线程访问 | shared memory |
| 单个线程(或work-item)可以访问 | local memory |
CUDA 支持多种存储器类型,线程代码可以从不同的存储空间访问数据,提高内核函数的执行性能。每个线程都拥有自己独立的存储空间,包括寄存器文件(Register File)和局部存储器(Local Memory),这些存储空间只有本线程才能访问。每个线程块允许内部线程访问共享存储器(Shared Memory),在块内进行线程间通信。线程网格内部的所有线程都能访问全局存储器(Global Memory),也可以访问纹理存储器(Texture Memory)和常量存储器(Constant Memory)中的数据。

① 寄存器文件(Register File)是 SM 片上存储器中最为重要的一个部分,它提供了与计算内核相匹配的数据访问速度。大容量的寄存器文件能够让更多的线程同时保持在活跃状态。这样当流水线遇到一些长延时的操作时,GPGPU可以在多个线程束之间快速地切换来保持流水线始终处于工作状态。这种特性在GPGPU中被称为零开销线程束切换(zero-cost warp switching),可以有效地掩藏长延时操作,避免流水线的停顿。
② 局部存储器(Local Memory)是每个线程自己独立的存储空间,局部存储器是私有的,只有本线程才能进行读写。
③ 共享存储器(Shared Memory)也是SM 片内的高速存储资源,它由一个线程块内部的所有线程共享。相比于全局存储器,共享存储器能够以类似于寄存器的访问速度读写其中的内容。
④ 全局存储器(Global Memory)位于设备端。GPGPU内核函数的所有线程都可对其进行访问,但其访存时间开销较大。
⑤ 常量存储器(Constant Memory)位于设备端存储器中,其中的数据还可以缓存在SM内部的常量缓存(Constant Cache)中,所以从常量存储器读取相同的数据可以节约带宽,对相同地址的连续读操作将不会产生额外的存储器通信开销。
⑥ 纹理存储器(Texture Memory)位于设备端存储器上,其读出的数据可以由纹理缓存(Texture Cache)进行缓存,也属于只读存储器。
六、同步机制
在SIMT 计算模型中,每个线程的执行都是相互独立的。然而在实际的应用和算法中,除向量加这种可完全并行的计算之外,并行的线程之间或多或少都需要某种方式进行协同和通信,例如:
① 某个任务依赖于另一个任务产生的结果,例如生产者-消费者关系;
② 若干任务的中间结果需要汇集后再进行处理,例如归约操作。
这就需要引入某种形式的同步操作,以Thread Block中的线程同步为例:

在CUDA 编程模型中,__syncthreads()可用于同一线程块内线程的同步操作,它对应的PTX 指令为bar 指令。该指令会在其所在程序计数器(Programe Counter,PC)位置产生一个同步栅栏(barrier),并要求线程块内所有的线程都到达这一栅栏位置才能继续执行,这可以通过监控线程的PC来实现。在线程同步的要求下,即便有些线程运行比较快而先到达bar指令处也要暂停,直到整个线程块的所有线程都达到bar指令才能整体继续执行。
七、总结
本文介绍了GPGPU编程的背景、CUDA编程实现步骤、软件到硬件的过度以及存储模型等内容,为后续介绍GPGPU架构提供理论基础。
相关文章:
通用图形处理器设计GPGPU基础与架构(二)
一、前言 本系列旨在介绍通用图形处理器设计GPGPU的基础与架构,因此在介绍GPGPU具体架构之前,需要了解GPGPU的编程模型,了解软件层面是怎么做到并行的,硬件层面又要怎么配合软件,乃至定出合适的架构来实现软硬件协同。…...
在一个使用了 Sass 的 React Webpack 项目中安装和使用 Tailwind CSS
要在一个使用了 Sass 的 React Webpack 项目中安装和使用 Tailwind CSS,可以按照以下步骤操作: 1. 安装 Tailwind CSS 及其依赖 首先,确保你的项目根目录下有 package.json 文件,然后运行以下命令来安装 Tailwind CSS 及其所需的…...
HDMI简介
本篇主要介绍HDMI常见接口以及TMDS传输技术。 文章目录 一、HDMI简介二、TMDS传输技术1.编码(encoder)2.并转串(serializer)——OSERDESE2原语3.单端转差分——OBUFDS源语 三、常见的几种信号传输方式 一、HDMI简介 HDMI(High-Definition Multimedia I…...
原作者带队,LSTM卷土重来之Vision-LSTM出世
与 DeiT 等使用 ViT 和 Vision-Mamba (Vim) 方法的模型相比,ViL 的性能更胜一筹。 AI 领域的研究者应该还记得,在 Transformer 诞生后的三年,谷歌将这一自然语言处理届的重要研究扩展到了视觉领域,也就是 Vision Transformer。后来…...
Fiddler 抓包工具抓https
Fiddler 抓包工具抓https...
详细谈谈负载均衡的startupProbe探针、livenessProbe探针、readnessProbe探针如何使用以及使用差异化
文章目录 startupProbe探针startupProbe说明示例配置参数解释 使用场景说明实例——要求: 容器在8秒内完成启动,否则杀死对应容器工作流程说明timeoutSeconds: 和 periodSeconds: 参数顺序说明 livenessProbe探针livenessProbe说明示例配置参数解释 使用…...
守望数据边界:sklearn中的离群点检测技术
守望数据边界:sklearn中的离群点检测技术 在数据分析和机器学习项目中,离群点检测是一项关键任务。离群点,又称异常值或离群点,是指那些与其他数据显著不同的观测值。这些点可能由测量误差、数据录入错误或真实的变异性造成。正确…...
python工作中遇到的坑
1. 字典拷贝 有些场景下,需要对字典拷贝一个副本。这个副本用于保存原始数据,然后原来的字典去参与其他运算,或者作为参数传递给一些函数。 例如, >>> dict_a {"name": "John", "address&q…...
中职网络安全wire0077数据包分析
从靶机服务器的FTP上下载wire0077.pcap,分析该文件,找出黑客入侵使用的协议,提交协议名称 SMTP 分析该文件,找出黑客入侵获取的zip压缩包,提交压缩包文件名 DESKTOP-M1JC4XX_2020_09_24_22_43_12.zip 分析该文件&…...
引领未来:在【PyCharm】中利用【机器学习】与【支持向量机】实现高效【图像识别】
目录 一、数据准备 1. 获取数据集 2. 数据可视化 3. 数据清洗 二、特征提取 1. 数据标准化 2. 图像增强 三、模型训练 1. 划分训练集和测试集 2. 训练 SVM 模型 3. 参数调优 四、模型评估 1. 评估模型性能 2. 可视化结果 五、预测新图像 1. 加载和预处理新图像…...
240707-Sphinx配置Pydata-Sphinx-Theme
Step A. 最终效果 Step B. 为什么选择Pydata-Sphinx-Theme主题 Gallery of sites using this theme — PyData Theme 0.15.4 documentation Step 1. 创建并激活Conda环境 conda create -n rtd_pydata python3.10 conda activate rtd_pydataStep 2. 安装默认的工具包 pip in…...
华为如何做成数字化转型?
目录 企业数字化转型是什么? 华为如何定义数字化转型? 为什么做数字化转型? 怎么做数字化转型? 华为IPD的最佳实践之“金蝶云” 企业数字化转型是什么? 先看一下案例,华为经历了多次战略转型…...
Python | Leetcode Python题解之第229题多数元素II
题目: 题解: class Solution:def majorityElement(self, nums: List[int]) -> List[int]:cnt {}ans []for v in nums:if v in cnt:cnt[v] 1else:cnt[v] 1for item in cnt.keys():if cnt[item] > len(nums)//3:ans.append(item)return ans...
TCP/IP模型和OSI模型的区别(面试题)
OSI模型,是国际标准化组织ISO制定的用于计算机或通讯系统间互联的标准化体系,主要分为7个层级: 物理层数据链路层网络层传输层会话层表示层应用层 虽然OSI模型在理论上更全面,但是在实际网络通讯中,TCP/IP模型更加实…...
UML建模工具Draw.io简介
新书速览|《UML 2.5基础、建模与设计实践 Draw.io是一个非常出色的免费、开源、简洁、方便的绘图软件,利用这款软件可以绘制出生动有趣的图形,包括流程图、地图、网络架构图、UML用例图、流程图等。它支持各种快捷键,免费提供了1000多张画图…...
qt udp 协议 详解
1.qt udp 协议链接举例 在Qt框架中,使用UDP协议进行通信主要依赖于QUdpSocket类。以下是一个基于Qt的UDP通信示例,包括UDP套接字的创建、绑定端口、发送和接收数据报的步骤。 1. 创建UDP套接字 首先,需要创建一个QUdpSocket对象。这通常在…...
ubuntu 换源
sudo apt update 错误如下 Ign:1 http://security.ubuntu.com/ubuntu focal-security InRelease Ign:2 http://us.archive.ubuntu.com/ubuntu focal InRelease Err:3 http://security.ubuntu.com/ubuntu focal-security Release SECURITY: URL redirect target…...
基于ssm的图书管理系统的设计与实现
摘 要 在当今信息技术日新月异的时代背景下,图书管理领域正经历着深刻的变革,传统的管理模式已难以适应现代社会的快节奏和高要求,逐渐向数字化、智能化的方向演进。本论文聚焦于这一转变趋势,致力于设计并成功实现一个基于 SSM&…...
python压缩PDF方案(Ghostscript+pdfc)
第一步:安装Ghostscript Ghostscript是一套建基于Adobe、PostScript及可移植文档格式(PDF)的页面描述语言等而编译成的免费软件。它可以作为文件格式转换器,如PostScript和PDF转换器,也为编程提供API。[1]PDF压缩本质…...
kotlin 基础
文章目录 1、安装 Java 和 Kotlin 环境2、程序代码基本结构3、变量的声明与使用4、数据类型5、数字类型的运算1)布尔类型2)字符类型3)字符串类型 6、 选择结构1)(if - else)2) 选择结构(when&am…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”
目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
C++_哈希表
本篇文章是对C学习的哈希表部分的学习分享 相信一定会对你有所帮助~ 那咱们废话不多说,直接开始吧! 一、基础概念 1. 哈希核心思想: 哈希函数的作用:通过此函数建立一个Key与存储位置之间的映射关系。理想目标:实现…...
