阅读 《大规模并行处理器程序设计》影印版心得 第六章 Performance Consideration

本文主要是介绍阅读 《大规模并行处理器程序设计》影印版心得 第六章 Performance Consideration,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

6.1 More on Thread Execution

 

warp的概念

 

warp是如何组织的:按x,y,z逐渐增大的方式来线性化多维方式组织的线程,然后从前往后,每32个线程为一个warp

 

The hardware executes an instruction for all threads in the same warp before moving to the next instruction. This is so called SIMD

 

但是有分支的情况下,warp表现就不那么好。就需要两个或多个pass去执行不同的分支。

 

reduction algorithm为例。图6.3显示了常规的并行化方案,最开始是编号为偶数(2的倍数)的线程计算编号为偶数的数组元素和其后续相邻(+1)元素的和,并且把和存储在编号为偶数的数组元素的位置;然后是编号为4倍数的线程计算编号为4的倍数的数组元素和其后续相邻(+2)元素的和,并且把和存储在编号为4的倍数的数组元素的位置;然后是编号为8的倍数的线程计算编号为8的倍数的数组元素和其后续相邻(+4)元素的和,并且把结果存储在编号为8的倍数的数组元素的位置......

 

图6.5显示了一个改进的并行化方案。主要是考虑到warp的结构:threadIdx.x值连续的32个线程组成一个warp。则巧妙设计如下:最开始是编号为0的线程计算编号0的数组元素和编号为256的数组元素的和,并且把和存储在编号为0的数组元素的位置,编号为1的线程计算编号为1的数组元素和编号为257的数组元素的和......;则经过第一轮以后,所有的和都放在了编号小于256的数组元素的位置了。并且,编号为0线程开始的warp(线程0到线程31)执行相同的分支,因此,不会增加多余的pass,节省了时间,提高了性能。

 

但是图6.4的算法并不能完全消除divergence,尤其是第五轮以后还会出现分支执行步调不一致的情况。

 

6.2 Global Memory Bandwidth

 

主要讨论global memory使用时的问题。 目标是最好一次性读出一段连续的内存空间,这样效率最高,性能最好。

 

注意:我们要达到的目的是连续的thread最好能读取连续的global memory空间。图6.6就显示了这样的效果。图6.6A图中,两个连续的thread在每次迭代中,都是读取同样列号的矩阵元素。则这些元素的存储空间不是连续的,对性能有负面影响。而在图6.6B图中,两个连续的thread在每次迭代中,都去读取同样行号的矩阵元素。则这些元素的存储空间是连续的,即同样一个warp(线程号threadIdx.x连续)中的线程读取连续的global memory空间,有助于提升性能。这里理解的一个关键是,warp中的线程的运行是SIMD的,每次迭代时,是先运行第一个线程的读取一个元素的操作,然后是下一个连续线程的读取一个元素的操作。因此,需要把这两个线程读取的空间连续起来,提升性能。

 

当算法是在没有办法让连续号的线程读取联系的存储空间时,可以考虑用tile技术,把global memory中的数据依次拷贝到shared memory中来提升性能。此时,即使相邻线程不读取联系空间,性能也不会太差。因为shared memory带宽比global memory宽多了。

 

 

 

6.3 Dynamic Partitioning of SM Resources

 

SM资源包括寄存器,thread block slot和thread slot,GPU可以动态配置这些资源的数量。但是要注意的是,这些资源都是有数量上限的。不合理的配置资源的数量,可能会导致SM的能力不能被充分利用。

 

对寄存器来说,也可能会发生performance cliff,即一个很小的资源利用的增加,可能会导致程序并行性方面的大的减弱并进而影响程序的性能。一个例子就是增加一个自动变量(寄存器变量),可能会导致一个SM中运行的block数量的减少(因为寄存器变量的数量),并进而导致总线程数量的减少。

 

但是在另外一些情况下,增加自动变量,却可能导致减少global memory访问的开销,并进而提升程序的性能。这里的一个计算很有意思:在一个global memory load和its use之间,如果有4条独立指令,并假定买个指令的执行时间是4个时钟。则4条指令将执行16个时钟。已知一个global memory latency是200个时钟,因此,我们至少需要200/16 = 14个warp来达到zero-overhead scheduling。即当一个线程进入等待global memory latency时,如果有至少14个warp,则一定可以找到一个warp来执行。如果增加自动变量能增加global memory load和its use之间的独立指令条数时,则用更少的warp都可以达到一定可以找到warp来执行的效果。

 

6.4 Data Prefetching

 

Data prefetching,跟6.3中最后谈到的内容有些相似。主要思想是:矩阵相乘算法中,把global memory中存储的Md元素存取到shared memory中,其实需要两步:1)从global memory到registers;2)从registers到shared memory中。但是原来的算法,在这两步之间无independent instructions,无法在内存读写忙时,提供更多的代码来执行。其改进思想如图6.13显示。先进行一个data prefetching(从global memory读到registers),然后进入循环。循环中,先把先前读入到registers中的数据传递到shared memory中,然后同步。然后在把下一步中要用到的数据(next tile)从global memory中读取到registers中,然后进行真正的点积运算(贡献出很多的independent instruction)。这里有两个假定:1)数据读取可以是异步的,即发出读取指令后,程序继续运行。只有程序需要用到要读取的数据时,线程才进入等待状态;

 

 

6.5 Instruction Mix

 

这一节很好理解。就是把循环语句改变为不循环的语句。即unroll the loop。 

 

把for (i = 1; i<=10;i++)  sum+=i;  变为sum = 1+2+3+4+...+10;  这样做,可以提升性能。少了i变量的加减运算,同时提升了对数组元素的访问性能。

 

 

6.6 Thread Granularity

 

主要意思是:很多情况下,把线程进行合并,可以有效利用线程所读取的数据(读一次,利用2次),提升性能。

 

 

6.7 Measured Performance and Summary

 

主要结论是:tiles技术是提升性能的关键。当tiles足够大时,则loop unrolling和data prefetching技术也变得重要起来。

 

这里是主要的一个研究方向:即自动优化技术,在特定硬件上综合各种优化技术达到最大的性能,而且要求这一过程是程序实现,自动进行的。有参考文献可以看。

 

 

这篇关于阅读 《大规模并行处理器程序设计》影印版心得 第六章 Performance Consideration的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/194225

相关文章

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

软件架构模式:5 分钟阅读

原文: https://orkhanscience.medium.com/software-architecture-patterns-5-mins-read-e9e3c8eb47d2 软件架构模式:5 分钟阅读 当有人潜入软件工程世界时,有一天他需要学习软件架构模式的基础知识。当我刚接触编码时,我不知道从哪里获得简要介绍现有架构模式的资源,这样它就不会太详细和混乱,而是非常抽象和易

C语言程序设计(数据类型、运算符与表达式)

一、C的数据类型 C语言提供的数据类型: 二、常量和变量 2.1常量和符号常量 在程序运行过程中,其值不能被改变的量称为常量。 常量区分为不同的类型: 程序中用#define(预处理器指令)命令行定义变量将代表常量,用一个标识符代表一个常量,称为符合常量。 2.2变量 变量代表内存中具有特定属性的一个存储单元,用来存放数据,在程序运行期间,这些值是可以 改变的。 变

C语言程序设计(选择结构程序设计)

一、关系运算符和关系表达式 1.1关系运算符及其优先次序 ①<(小于) ②<=(小于或等于) ③>(大于) ④>=(大于或等于 ) ⑤==(等于) ⑥!=(不等于) 说明: 前4个优先级相同,后2个优先级相同,关系运算符的优先级低于算术运算符,关系运算符的优先级高于赋值运算符 1.2关系表达式 用关系运算符将两个表达式(可以是算术表达式或关系表达式,逻辑表达式,赋值表达式,字符

第六章习题11.输出以下图形

🌏个人博客:尹蓝锐的博客 希望文章能够给到初学的你一些启发~ 如果觉得文章对你有帮助的话,点赞 + 关注+ 收藏支持一下笔者吧~ 1、题目要求: 输出以下图形

【阅读文献】一个使用大语言模型的端到端语音概要

摘要 ssum框架(Speech Summarization)为了 从说话人的语音提出对应的文本二题出。 ssum面临的挑战: 控制长语音的输入捕捉 the intricate cross-mdoel mapping 在长语音输入和短文本之间。 ssum端到端模型框架 使用 Q-Former 作为 语音和文本的中介连接 ,并且使用LLMs去从语音特征正确地产生文本。 采取 multi-st

智能工厂程序设计 之1 智能工厂都本俱的方面(Facet,Aspect和Respect)即智能依赖的基底Substrate 之1

Q1、昨天分别给出了三个智能工厂的 “面face”(里面inter-face,外面outer-face和表面surface) 以及每个“面face” 各自使用的“方”(StringProcessor,CaseFilter和ModeAdapter)  。今天我们将继续说说三个智能工厂的“方面” 。在展开之前先看一下三个单词:面向facing,取向oriented,朝向toword。理解这三个词 和

处理List采用并行流处理时,通过ForkJoinPool来控制并行度失控的问题

在使用parallelStream进行处理list时,如不指定线程池,默认的并行度采用cpu核数进行并行,这里采用ForJoinPool来控制,但循环中使用了redis获取key时,出现失控。具体上代码。 @RunWith(SpringRunner.class)@SpringBootTest(classes = Application.class)@Slf4jpublic class Fo

C语言程序设计 笔记代码梳理 重制版

前言 本篇以笔记为主的C语言详解,全篇一共十章内容,会持续更新基础内容,争取做到更详细。多一句没有,少一句不行!  形而上学者谓之道,形而下学者谓之器 形而上学者谓之道,形而下学者谓之器 第1章 C语言的流程 1.C程序经历的六个阶段 编辑(Edit)预处理(Preprocess)编译(Compile)汇编(Assemble)链接(Link)执行(Execute)  2.