第4章 循环变换

4.1 适配体系结构特征的关键技术

由于高级语言隐藏了底层硬件体系结构的大量细节,如果不经过优化直接将高级程序设计语言编写的程序部署在底层硬件上,往往无法充分利用底层硬件体系结构的处理能力。                               

算子融合不仅可以提高计算密度,还可以避免相邻算子之间通过GPU设备内存通信引入的数据访问开销。

循环变换和不同循环变换之间的组合是实现面向底层硬件体系结构的重要优化手段。本章将基于多面体模型详细介绍优化编译器实现循环变换及不同循环变换之间组合的方式,并介绍各种循环变换的应用场景,以及一些循环变换之间的关系。

4.2 预处理

只要维持程序的循环携带依赖,那么循环变换总是有效的。在开始分析依赖关系之前,优化编译器应该提供一些能够对循环嵌套实现预处理的机制。一方面,预处理能够简化依赖测试或精确依赖分析的过程;另一方面,预处理也能够消除一些复杂的循环携带依赖,为实现更多的循环变换创造环境。

4.2.1 循环正规化

循环正规化使得循环嵌套中每个循环下界从0开始运行到某个确定的上界,并且循环的步长为1.同时,使用新的循环索引变量替换的仿射函数表达式区替换原循环变量在循环内的所有引用。即循环的下界为0,上界为(U-L)/r,步长为1,。原循环索引变量为i,之后为r*i + L。注意r应该是一个具体的常数值而不是符号常亮,否则难以通过静态分析来判定依赖是否存在。尽管可能通过引入谓词条件的方式将非仿射表达式转换为仿射表达式的形式,但这种向上近似的方法往往会导致冗余的循环跌打,程序的语义则通过引入的谓词条件来保证。

4.2.2 死代码删除

在实际应用中,可能会存在一些不会被其他有用的语句引用结果的语句,即程序的死代码。有用的语句是指用于输出程序结果的代码,或者那些再被优化的程序中仍然需要执行的代码。

死代码删除可以在计算出程序的数据流信息之后,利用向下暴露集与程序迭代空间以及依赖关系之间的基本操作来完成,其基本思想是先根据近似数据流分析方法计算出被优化的程序片段的向下暴露集,并依此计算出所有向下暴露集中语句实例的流依赖源点的集合,将二者集合求并,得到一个新的集合,向这些变量写入数据的语句实例都不会是死代码,重复该过程,直到求并之后的集合不再发生变化。由于死代码可以与其他语句产生数据流关系,因此将所有死代码语句导致的依赖从数据流关系和各种依赖关系中删除,减少编译器对程序实施循环变换的约束。

4.2.3 别名分析

别名分析阻碍优化编译器分析依赖关系最关键的因素之一,特别是对以多面体模型为基础的优化编译器而言,因为多面体没有办法判定不同内存地址单元之间的别名关系,也就无法确定语句实例之间是否有依赖。

大多数基于多面体模型的优化编译器只是简单地认为数组之间不再存在别名关系。

一种常用的方法是在程序设计语言级别引入辅助别名分析或者消除别名的语言特性。例如,C语言提供的restrict关键字。另一种方式是优化编译器在实施程序转换时,对可能产生别名关系的数组进行标记,并依靠运行时技术确定别名关系是否存在。

4.2.4 迭代空间分裂

为了减少二维stencil中空间维度之间的长距离依赖在每个维度上的距离向量分量,可以采用一种称为迭代空间分裂的方法。

对原迭代空间中非依赖方向进行切割,同一时间维度上的子空间可以通过折叠,将原来的依赖转换。迭代空间分裂为子空间的折叠创造了条件,但子空间的折叠却需要依靠多面体模型对循环迭代空间进行一维或多维反向的循环偏移或反转变换才能获得有利于循环变换的迭代空间。

4.3 多面体模型中的循环变换

与传统的并行编译器所采用的幺模矩阵相比,多面体模型具备以下几个特点:
        1. 应用范围广。幺模矩阵只能处理完美嵌套循环,而多面体模型对输入程序的约束更少,不仅处理完美循环嵌套,而且对非完美循环也支持。
        2. 表示能力强。幺模矩阵只能处理循环变换、切斜和反转等变换。而多面体还能处理循环分块、合并和分布等在内的几乎所有循环变换。
        3. 优化空间大。多面体模型能处理更多的循环变换的组合。

除了面向通用体系结构的源到源优化工具Pluto和PPCG外,GCC、LLVM、Opn64和IBM XL编译器都集成了多面体优化相关的模块。也在深度神经网络和自动优化和部署受到了广泛的关注:MLIR, TensorComprehensions,Tiramisu, PlaidML/Stripe和Diesel等深度学习编译器中发挥了不可替代的作用。

4.3.1 循环变换分类

根据循环变换对程序特征的改变,分为以下几种:
        1. 改变程序算法设计:是通过对算法的调整来降低时间或空间复杂度的。例如,在不考虑稳定性的前提下,可以使用快排代替冒泡排序。
        2. 改变程序计算顺序:往往是为了提升程序的并行性或数据的局部性。例如循环合并就是为了缩短相邻循环嵌套访问数据之间的“生产-消费”距离、提升数据的时间局部性而实现的循环变换。
        3. 仅改变循环结构、但不改变程序计算顺序:主要是为了生成对目标体系结构友好的代码而设计或实现的。例如循环展开就是一种为了充分利用细粒度指令流水并行而设计的循环变换。
        4. 改变程序数据布局和被访问内存地址单元:充分利用目标体系结构上的存储层次结构。

编译器很难实现第一种循环变换,基于多面体的编译器能够自动实现后三种的循环变换及其组合。后三种循环变换几乎都需要考虑目标体系结构的特征,因此如何在多面体模型中实现对目标体系结构的抽象是实现循环变换的关键。

4.3.2 循环变换的复杂性

基于多面体模型的循环变化将循环的迭代空间表示成空间多面体,并通过多面体上的几何操作达到分析和优化程序的目的。多面体模型利用迭代空间、访存映射、依赖关系和调度表示程序及其语义。其中,调度表示语句实例与其对应的字典序之间的仿射函数,多面体模型实现循环变换的方法就是在满足依赖关系的前提下,将一种调度转换成另一种调度的过程,该过程也被称为调度变换。多面体模型首先将循环嵌套内的语句实例构成的集合表示为空间多面体的形式。从几何角度来看,多面体模型上的调度变换实质上就是多维空间几何的变基过程。

// CPU 一段可并行循环
for(t = 0; t < T; t+=1)for(i = 0; i < N; i+=1)A[t+1][i] = 0.25 * (A[t][i+1] -2*A[t][i] + A[t][i-1]);// GPU 二段可并行循环
for(t = 0; t < T; t+=1)for(it = 0; it < (N-2)/4; it+=1)for(ip = max(1, 4*ip); ip < min(N-1, 4*ip+4); ip+=1)A[t+1][ip] = 0.25 * (A[t][ip+1] -2*A[t][ip] + A[t][ip-1]);

只考虑并行性的前提下,循环变换的代码在硬件上的部署似乎看起来没有那么麻烦。然而,一个无法忽视的问题是现代体系结构上的存储层次结构。尽管一些底层的编译技术已经充分考虑到如寄存器分配、指令流水线并行等细粒度策略,但是面向高速缓存的数据局部性优化却是循环变换不得不考虑的问题。

在基于多面体的编译器中,代码生成阶段的输入是表示程序迭代空间的集合和表示程序调度的映射。其中,表示程序调度的映射必须是从语句实例集合到字典序之间的仿射函数。

对迭代空间进行粗暴地矩形划分是非法的,因为任意两个水平相邻的分块之间存在依赖环,而多面体模型的代码生成器限制循环只能延(t,i)坐标轴方向切割。细看之后发现,沿i轴获得循环分块是合法的。接下来解决t轴切割。t轴的切割方向与程序中的两个依赖,即左上和右上方向的依赖都相交。如果沿着两个依赖的其中一个方向进行切割并构造新的分块形状。不难发现,这两种分块形状都不会导致任意方向相邻两个分块之间的依赖环。

要构造上述分块,i轴保持不变,另外一个坐标轴的指向左上或右上的依赖方向平行,需要编译器自动实现对循环分块友好的循环变换及这些循环变换的不同组合,这对编译器很重要也很困难。

循环变换的目的有时候是互相冲突的,以程序并行性和数据局部性为例,上述分块没有实现最大化程序并行性的目的,尽管提高了数据局部性。

带有OpenMP编译指示的代码在运行时有同步开销,编译指示在循环嵌套的层数越靠近,同步的开销就越小。循环分块增大了同步开销,因此损失了程序并行性。

4.3.3 Pluto调度算法

Pluto算法以自动实现循环分块为目的,在实施循环分块之前试图寻找能够最大化循环分块可能性的循环变化组合。

Pluto调度算法的核心是兼顾程序并行性和数据局部性的前提下,利用一种定义良好的代价模型,自动确定有利于实现循环分块的顺序关系,通过计算原始程序的顺序关系和新的顺序关系之间的映射函数,自动实现循环分块友好的循环变换组合。

4.4 仿射循环变换

任何能用多维仿射变换表示的循环变换都成为仿射循环变换。Pluto调度算法先进行仿射变换,然后在循环分块。

4.4.1 循环交换interchange

向量化:使用向量寄存器;并行化:无依赖;

循环交换将完美嵌套循环的两个循环顺序进行交换,通过这种技术既可以将可向量化的循环移动到循环嵌套的最内层以提高程序的向量化效果,也可以将可并行化的循环移动到循环嵌套最外层以增加程序的并行粒度,减少同步开销。

Pluto调度算法的代价模型是面向多核架构设计的,所以Pluto算法在实现循环交换时,更倾向于将可并行化的循环移动到循环嵌套的外层,以提高并行的粒度,并降低同步开销。

4.4.2 循环反转reversal

循环反转是一种将循环嵌套某一层循环的迭代方向进行反转,并将循环步长设置为原始值的相反数。

for (int i = 1; i < M; i++)for (int j = 1; j < N; j++)for (int k = 0; k < K - 1; k++)A[i][j][k] = A[i][j-1][k+1] + A[i-1][j][k+1];// reverse loop
for (int k = K-2; k >= 0; k--)#pragema omp parallel forfor (int i = 1; i < M; i++)for (int j = 1; j < N; j++)A[i][j][-k] = A[i][j-1][-k+1] + A[i-1][j][-k+1];

4.4.3 循环延展scaling

循环延展通过延展循环索引变量的取值范围和循环步长的技术,目的在于将程序中不规则的依赖转换成灾迭代空间上全局一致的依赖,从而使程序迭代之间的依赖距离向量分量能够用整数表示,依此来为其他循环变换创造机会。

for (int i = 0; i < N; i++)f[i] = fin[i];
for (int i = 0; i < N/2; i++)g[i] = f[2*i+1] * f[2*i-1];
for (int i = 0; i < N; i++)h[i] = g[i/2+1] * g[i/2];

将g[i]循环以延展为2展开,所有循环迭代之间的依赖在整个迭代空间上全局一致,且3个循环还可以合并。

4.4.4 循环倾斜skewing

循环倾斜通过改变完美循环嵌套对应迭代空间形状的循环变换技术,但并不会改变迭代之间的执行顺序。例如(t, i) --> (t, 2t+i)。

for(t = 0; t < T; t+=1)for(i = 0; i < N; i+=1)A[t+1][i] = 0.25 * (A[t][i+1] -2*A[t][i] + A[t][i-1]);

4.4.5 循环合并fussion

循环合并是一种通过将多个循环嵌套融合在一起形成一个统一的迭代空间,从而便于编译器实现其他优化的循环变换技术。循环合并本身是一个非常复杂的过程,合并后的循环可能会失去并行性或无法实现循环分块,因为可能产生的依赖问题。循环合并通过循环的融合缩短程序数据之间的“生产--使用”距离,从而提高数据的局部性。

4.4.6 循环分裂fission

循环分裂是一种将一个循环嵌套在分裂成多个循环嵌套的循环变换技术。循环分裂通过将循环嵌套某层循环上的循环携带依赖转换为循环无关依赖,来提升循环的并行性。

4.5 近似仿射变换

在仿射循环变换中,用于循环变换的表达式只包含加减法,乘法以及这些操作的组合,并且表示循环变换的仿射变换中不会涉及存在量词。在一些循环变换中,除法、取模以及存在量词是不可避免的,所以需要借助近似仿射表达式来表示循环变换。

4.5.1 循环分块blocking

循环分块将循环嵌套空间划分成不同的分块并改变循环迭代执行顺序的循环变换技术。如果在未经循环倾斜的原始迭代空间上能够实现正确的循环分块,那么就称为矩形分块。在经过一些仿射循环变换的组合之后才能进行循环分块所得到形状可能是平行四边形后者其他形状。

4.5.2 循环分段strip-mining

循环分段将一个循环的迭代空间分成多个子集,并将每个子集作为一个调度单元进行执行的循环变换技术。在多核架构中,循环分段的实现往往是隐式地分配单个循环迭代空间的不同子集给不同线程。但是在多级并行硬件抽象的体系结构,例如GPU上的线程块和线程,循环分段必须显式执行。

由编译器显式实现的循环分段往往会带来额外的循环执行开销,因为引入了新的循环边界判断条件。除非能提升程序的并行性,否则并不鼓励在优化编译器中显示地实现循环分段。循环分段也可看做循环分块在单层循环上的特殊情况。

4.5.3 循环展开压紧unroll and jam

循环展开压紧将某两层的外层循环展开后再将内层循环进行合并的循环变换技术,压紧效果在于减少了向量寄存器取数操作的次数,和展开效果在于增加不同计算功能部件之间的指令流水线并行效率。

4.6 代码生成过程的循环变换

代码生成过程中的循环变换包括分块分离、循环展开和循环剥离。

4.6.1 分块分离tile isolation

在迭代空间边界上由于与迭代空间相交而被舍去部分区域的分块被称为半块,其他没有被舍去的分块为整块。分块分离式一种将半块和整块分离,以消除循环嵌套中的重叠边界条件限定条件(min、max)。

分开分离通过消除生成代码中循环边界的min和max等限定边界操作,使得生成的代码能够对一些领域特定的加速芯片友好。

4.6.2 循环展开unrolling

循环展开是一种通过展开循环迭代来降低循环条件分支开销的循环变换技术,提高指令间流水并行,并降低用于循环边界判定的控制开销,还为向量化创造条件,但注意寄存器溢出。

4.6.3 其他循环优化

循环剥离peeling将循环某些迭代从循环主体中剥离出来的循环变换技术。循环中有时只有部分迭代会产生依赖,当这些循环迭代是循环的前几个或后几个迭代的时候,优化编译器就可以通过循环剥离的方法,将原来循环转换为两部分。

循环判断外提unswitching将循环内与循环索引无关的条件谓词外提到循环外的技术,降低分支开销,减少代码量。

4.7 循环压紧

循环压紧coalescing将多层循环嵌套压缩成单层循环的技术。

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

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

相关文章

C# | DBSCAN聚类算法实现 —— 对直角坐标系中临近点的点进行聚类

C# | DBSCAN聚类算法实现 聚类算法是一种常见的数据分析技术&#xff0c;用于将相似的数据对象归类到同一组或簇中。其中&#xff0c;DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;是一种基于密度的聚类算法&#xff0c;能够有效…

Spark有两种常见的提交方式:client 模式和 cluster 模式对机器 CPU 的影响

Spark有两种常见的提交方式&#xff1a;client 模式和 cluster 模式。这两种方式对机器 CPU 的影响略有不同 &#xff0c;请参考以下说明 Client 模式&#xff1a; 在 Client 模式下&#xff0c;Spark Driver 运行在提交任务的客户端节点上&#xff08;即运行 spark-submit 命…

云服务器利用Docker搭建sqli-labs靶场环境

一、安装宝塔面板 使用xshell、electerm、SecureCRT等远程终端连接登陆上云服务器&#xff0c;在Linux宝塔面板使用脚本安装 安装后&#xff0c;如下图&#xff1a;按照提示&#xff0c;在云服务器防火墙/安全组放行Linux宝塔面板的端口 在浏览器打开上述网址&#xff0c;登…

开源软件合集(Docker)

Docker安装 1.安装命令&#xff1a;curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun2.启动&#xff1a;systemctl start docker3.停止&#xff1a;systemctl stop docker4.重启&#xff1a;systemctl restart docker5.开机启动&#xff1a;systemctl enab…

【SpringSecurity】七、SpringSecurity集成thymeleaf

文章目录 1、thymeleaf2、依赖部分3、定义Controller4、创建静态页面5、WebSecurityConfigurerAdapter6、权限相关7、当用户没有某权限时&#xff0c;页面不展示该按钮 1、thymeleaf 查了下读音&#xff0c;leaf/li:f/&#xff0c;叶子&#xff0c;前面的单词发音和时间time一…

JAVA- n的阶乘Java版

输入一个整数 n&#xff0c;请你编写一个函数&#xff0c;int fact(int n)&#xff0c;计算并输出 n 的阶乘。 输入格式 共一行&#xff0c;包含一个整数 n 。 输出格式 共一行&#xff0c;包含一个整数表示 n 的阶乘的值。 数据范围 1≤n≤10 输入样例&#xff1a; 3输出样例&…

【算法训练-数组 三】数组中的第K个最大元素(TOPK问题|寻找第K大)

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【寻找第K大】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…

九、适配器模式

一、什么是适配器模式 适配器模式&#xff08;Adapter&#xff09;的定义如下&#xff1a;将一个类的接口转换成客户希望的另外一个接口&#xff0c;使得原本由于接口不兼容而不能一起工作的那些类能一起工作。 适配器模式&#xff08;Adapter&#xff09;包含以下主要角色&…

WebGPT VS WebGPU

推荐&#xff1a;使用 NSDT编辑器 快速搭建3D应用场景 随着WebGPU的引入&#xff0c;Web开发发生了有趣的转变&#xff0c;WebGPU是一种新的API&#xff0c;允许Web应用程序直接访问设备的图形处理单元&#xff08;GPU&#xff09;。这种发展意义重大&#xff0c;因为 GPU 擅长…

【MySQL】用户管理

之前我们一直都使用root身份来对mysql进行操作&#xff0c;但这样存在安全隐患。这时&#xff0c;就需要使用MySQL的用户管理 目录 一、用户 1.1 用户信息 1.2 添加用户 1.3 删除用户 1.4 修改用户密码 二、用户权限 2.1 赋予授权 2.2 回收权限 一、用户 1.1 用户信息…

【Axure高保真原型】中继器网格图片拖动摆放

今天和大家分享中继器网格图片拖动摆放的原型模板&#xff0c;我们可以通过鼠标拖动来移动图片&#xff0c;拖动过程其他图标会根据图片拖动自动排列&#xff0c;松开鼠标是图片停放在指定位置&#xff0c;其他图标自动排列。那这个模板是用中继器制作的&#xff0c;所以使用也…

[机器学习]分类算法系列①:初识概念

目录 1、概念 2、数据集介绍与划分 2.1、数据集的划分 2.2、sklearn数据集介绍 2.2.1、API 2.2.2、分类和回归数据集 分类数据集 回归数据集 返回类型 3、sklearn转换器和估计器 3.1、转换器 三种方法的区别 3.2、估计器 3.2.1、简介 3.2.2、API 3.3、工作流程 …

【软考】系统集成项目管理工程师(一)信息化基础知识【6分】

一、信息与信息系统 1、信息技术 为解决信息的采集、加工、存储、传输、处理、计算、转换、表现等问题而不断繁荣发展 核心-传输技术&#xff08;通常指通信、网络等&#xff09; 2、信息的质量属性 特点&#xff1a;客观性、普遍性 属性描述精确性对事物状态描述的精准程度…

图书馆项目Java阅览室管理系统jsp源代码MySQL

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 图书馆项目 系统有1权限&#xff1a;管理员 用所技术…

LeetCode 面试题 02.01. 移除重复节点

文章目录 一、题目二、C# 题解 一、题目 编写代码&#xff0c;移除未排序链表中的重复节点。保留最开始出现的节点。 点击此处跳转题目。 示例1: 输入&#xff1a;[1, 2, 3, 3, 2, 1] 输出&#xff1a;[1, 2, 3] 示例2: 输入&#xff1a;[1, 1, 1, 1, 2] 输出&#xff1a;[1, …

Centos7 安装 docker

1、前提条件 目前&#xff0c;CentOS 仅发行版本中的内核支持 Docker。Docker 运行在CentOS7 (64)上&#xff0c; 要求系统为64位、Linux系统内核版本为 3.8以上 查看自己系统的内核 cat /etc/redhat-release 或 uname -r 2、卸载旧版本 旧版本的 Docker 的名称为docker或doc…

【注册岩土】Python土力学与基础工程计算.PDF-摩尔-库伦强度理论

8.3 Python求解 Python求解代码如下&#xff1a; 1.import math 2. 3.sigma1 300 # 最大主应力&#xff0c;单位 kPa 4.sigma3 100 # 最小主应力&#xff0c;单位 kPa 5.alpha 30 # m-n面与最小主应力方向夹角&#xff0c;单位度 6. 7.rad_alph…

【MYSQL学习笔记】管理MYSQL和使用MYSQL语句

一、前言 MySQL提供了大量的SQL语句用于管理。很多时候&#xff0c;通过SSH远程连接时&#xff0c;只能使用SQL命令&#xff0c;所以&#xff0c;了解并掌握常用的SQL管理操作是必须的。 二、管理MYSQL 输入SQL后&#xff0c;记得加一个;&#xff0c;再回车执行该语句。虽然…

Matlab图像处理-图像旋转

基本概念 图像的旋转变换属于图像的位置变换&#xff0c;通常是以图像的中心为原点&#xff0c;将图像上的所有像素都旋转一个相同的角度。旋转后&#xff0c;图像的大小一般会改变。图像的旋转变换是指以图像的中心为原点&#xff0c;将图像上的所有像素都旋转同一个角度的变…

MFA 与 ADSelfService Plus 的身份验证!

随着信息技术的不断进步&#xff0c;网络威胁也在不断演化。为了保护敏感数据和网络资源&#xff0c;企业和组织需要采取更多的安全措施。多重因素认证&#xff08;MFA&#xff09;已经成为了现代安全战略的核心组成部分之一。在这篇文章中&#xff0c;我们将深入探讨MFA&#…