一种开发循环代码中潜在可向量化循环的方法与流程

文档序号:20680732发布日期:2020-05-08 18:22阅读:481来源:国知局
一种开发循环代码中潜在可向量化循环的方法与流程

本发明属于编译优化领域,特别涉及一种开发循环代码中潜在可向量化循环的方法。



背景技术:

向量计算是一种simd(singleinstructionstream,multipledatastream)并行计算方式,使一条指令同时处理多份数据,以提高程序并行度及性能,从而减小计算成本并产生经济效益。由于高性能、大数据、人工智能等应用类型往往具有对大规模数据执行相同逻辑运算的特征,向量计算能够给这些应用带来显著的加速效果。随着第一代商用向量处理器——英特尔奔腾2(intelpentiumii)于1996年问世,向量计算功能逐渐成为通用处理器的标配。除向量处理器外,硬件制造商们还开发了一系列的向量计算指令集以便于程序员在软件开发中使用向量计算技术,例如mmx、sse和avx等。而主流编译器,如gcc、llvm-clang、icc等,也在逐步支持自动向量化功能,在编译预处理阶段将可向量化的循环代码自动使用向量指令实现。自动向量化给程序员带来了极大的方便,即使是不了解体系结构和向量指令的程序员也可以轻松写出向量化的代码。然而在常见应用的程序代码中,部分循环存在跨迭代依赖,而对存在跨迭代依赖的循环进行向量化可能导致错误的计算结果,因此有大量的循环因为存在跨迭代依赖而不能被向量化。为了充分利用向量处理器的优势,可通过一定的循环变换技巧来避免部分跨迭代依赖对计算结果正确性的破坏,以使尽可能多的循环被向量化,从而提升程序性能。在处理跨迭代依赖方面,现有的多面体编译优化技术通过仿射调度在提高程序并行度的同时又不使跨迭代依赖破坏计算结果的正确性。但仿射调度通常适用于mimd(multipleinstructionstream,multipledatastream)并行方式,在实际程序代码中实施仿射变换往往需要加入分支语句,导致程序对多份数据的逻辑操作不一致,因此不能用于开发潜在可向量化循环。目前,以有效开发潜在可向量化循环为目标的循环变换通常基于程序员的经验手动实现,编程难度较大且容易忽略部分潜在可向量化循环,缺乏一种有效方法来指导这一变换过程。



技术实现要素:

本发明的目的在于提供一种开发循环代码中潜在可向量化循环的方法,以克服现有方法在开发潜在可向量化循环过程编译难度大的问题。

为达到上述目的,本发明采用如下技术方案:

一种开发循环代码中潜在可向量化循环的方法,包括以下步骤:

步骤1)、检测数据依赖:根据伯恩斯坦条件扫描获取循环代码中的数据依赖,根据读写顺序判断数据依赖的初始类型;

步骤2)、数据依赖模型化:通过定位三元组分别表示数据依赖源语句的位置和数据依赖目标语句的位置,计算数据依赖源语句至数据依赖目标语句的距离向量,根据距离向量获取数据依赖的迭代类型,建立由数据依赖源语句、数据依赖目标语句、定位三元组、距离向量、数据依赖的初始类型及数据依赖的迭代类型构成的初始依赖表;

步骤3)、对初始依赖表进行数据缓冲:扫描初始依赖表,若初始依赖表存在自反依赖,且该自反依赖的源/目标语句之间不存在自正依赖,则将该自反依赖复制插入到该自反依赖的源/目标语句代码下方,同时通过缓冲数组分别替换自反依赖中的写数组以及复制的该自反依赖中的读数组,更新依赖表并重新执行步骤3)直至初始依赖表中不存在自反依赖;若不存在自反依赖,则进入步骤4);

步骤4)、对不存在自反依赖的依赖表进行语句重排:扫描不存在自反依赖的依赖表,若存在交叉依赖,则将交叉依赖的数据依赖源语句以及与交叉依赖数据依赖源语句交叉依赖的数据依赖目标语句从当前循环l移动到循环l+1中;若不存在交叉依赖,则结束。

进一步的,所述读地址的序号i从语句表达式中最靠近赋值符的读地址依次递增,最靠近赋值符的读地址序号i=1。

进一步的,定位三元组包括循环位置、迭代步数和语句相对位置。

进一步的,数据依赖源语句至数据依赖目标语句的距离向量由数据依赖目标语句和数据依赖源语句相减得到。

进一步的,根据距离向量划分的依赖类型包括自依赖、交叉依赖、同迭代依赖和跨循环依赖。

进一步的,步骤1)中,根据伯恩斯坦条件判断任意两条语句是否存在数据依赖的条件,若任意两条语句同时满足:

a、该两条语句访问相同的地址;

b、至少一条语句包含写操作;

c、该两条语句被并行执行;

则该两条语句之间存在数据依赖。

进一步的,根据读写顺序划分的依赖类型包括:目标语句在源语句写之后读,则数据依赖为正依赖;目标语句在源语句读之后写,则数据依赖为反依赖;目标语句在源语句写之后写,则数据依赖为输出依赖。

进一步的,步骤4)中,交叉依赖包括直接交叉依赖和间接交叉依赖。

进一步的,间接交叉依赖指s1作为目标语句直接交叉依赖于s2语句,s2作为目标语句又直接交叉依赖于s3语句,则s1作为目标语句间接交叉依赖于s3语句。

进一步的,将交叉依赖中数据依赖源语句以及与交叉依赖数据依赖源语句交叉依赖的数据依赖目标语句从当前循环l移动到循环l+1中,若循环l+1不存在,则创建循环l+1,使交叉依赖转变为跨循环依赖。

与现有技术相比,本发明具有以下有益的技术效果:

本发明一种开发循环代码中潜在可向量化循环的方法,根据伯恩斯坦条件扫描获取循环代码中的数据依赖,根据读写顺序判断数据依赖的初始类型,采用定位三元组分别表示数据依赖源语句的位置和数据依赖目标语句的位置,计算距离向量并根据距离向量划分数据依赖类型,然后通过对自反依赖语句进行数据缓冲和对交叉依赖语句进行重排,采用数据缓冲消除自反依赖,采用语句重排消除交叉依赖,将部分原本不能够被编译器自动向量化的循环转换为可被向量化的循环,本发明通过形式化算法减小循环代码中数据依赖对向量化的影响,该方法能够有效提高程序向量化效率,提高程序在向量处理器上执行的性能,且操作性良好。

附图说明

图1为阐述具体实施方式的示例循环代码。

图2为阐述具体实施方式的经过数据缓冲后的示例循环代码。

图3为阐述具体实施方式的经过语句重排后的示例循环代码。

具体实施方式

下面结合附图对本发明做进一步详细描述:

为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步地详细说明。应当理解,此处描述的实施用例仅用于解释本发明的基本构想,并不用于限定本发明的保护范围。

潜在可向量化循环是有确定的迭代次数、迭代变量递增、对多份数据的逻辑操作一致、存在跨迭代依赖但不是自正依赖的循环。

本发明的实施用例为如图1所示的循环代码;其中,s1语句的b[i]为写地址,a[i]为读地址1;s2语句的a[i]为写地址,a[i+1]为读地址1;s3语句的c[i]为写地址,a[i]为读地址1。

一种开发循环代码中潜在可向量化循环的方法,包括以下步骤:

1、进行数据依赖检测:

根据伯恩斯坦条件扫描获取循环代码中的数据依赖,根据读写顺序判断数据依赖的初始类型;

2、将数据依赖模型化:通过定位三元组分别表示数据依赖源语句的位置和数据依赖目标语句的位置,定位三元组包括循环位置l、迭代步数i和语句相对位置s,计算数据依赖源语句至数据依赖目标语句的距离向量,根据距离向量获取数据依赖的迭代类型,建立由数据依赖源语句、数据依赖目标语句、定位三元组、距离向量、数据依赖的初始类型及数据依赖的迭代类型构成的初始依赖表;

具体的:由定位三元组(l,i,s)表示一条赋值语句,即表示数据依赖源语句和数据依赖目标语句,赋值语句具体形式为:写地址=表达式(读地址1、读地址2、…读地址i…读地址n);用xs(ls,is,ss)表示数据依赖源语句,用xt(lt,it,st)表示数据依赖目标语句,用d(δl,δi,δs)=xt-xs=(lt-ls,it-is,-表示一条数据依赖源语句至数据依赖目标语句的距离向量。读地址的序号i从语句表达式中最靠近赋值符的读地址依次递增,最靠近赋值符的读地址序号i=1。本申请中潜在可向量化循环为单层循环。

根据距离向量划分的依赖类型包括:

a、δl=0且δi≠0且δs=0,数据依赖为自依赖;

b、δl=0且δi≠0且δs≠0,数据依赖为交叉依赖;

c、δl=0且δi=0,数据依赖为同迭代依赖;

d、δl≠0,数据依赖为跨循环依赖。

数据依赖模型化指采用源语句向量xs、目标语句向量xt、距离向量d、循环位置l、迭代步数i和语句相对位置s对数据依赖进行描述。

具体如图1所示的循环代码,根据伯恩斯坦条件扫描循环代码中的数据依赖,归纳得到依赖表(表1)。以数据依赖d1为例,其源语句所在循环l1的位置为第1位,迭代步数为i,语句位置为1,则表示d1源语句位置的三元组为(1,i,1);同理,表示d1目标语句的三元组为(1,i+1,2);确定源语句和目标语句后,将目标语句的位置与源语句的位置相减,得到距离向量(0,1,1)。

表1初始依赖表

3、对初始依赖表进行数据缓冲:

数据缓冲用于消除自反依赖。

对所建立的依赖表进行数据扫描,若初始依赖表存在自反依赖,且该自反依赖的源/目标语句之间不存在自正依赖,则将该自反依赖复制插入到该自反依赖的源/目标语句代码下方,同时通过缓冲数组分别替换自反依赖中的写数组以及复制的该自反依赖中的读数组,更新依赖表并重新执行步骤3)直至初始依赖表中不存在自反依赖;若不存在自反依赖,则进入步骤4);

具体如:以表1中自反依赖d2为例,在自反依赖d2的源/目标语句s2的下方插入一条s2的拷贝,用临时数组buf替换s2中左边的写数组,并用buf替换自反依赖d2下一条语句中右边的读数组(即用buf替换拷贝的自反依赖d2的源/目标语句中的读数组),以消除初始依赖表中的自反依赖d2。对于其他自反依赖,也可采用类似的步骤消除。每消除一个自反依赖,就更新一次依赖表,然后重新检查自反依赖,直到代码中不存在自反依赖。图1所示循环代码在完成数据缓冲后得到如图2所示的代码,并得到新的依赖表(表2)。在完成数据缓冲后,循环代码中所有的自反依赖皆被消除。

表2完成数据缓冲后的依赖表

4、语句重排方法:

语句重排用于消除交叉依赖。对于交叉依赖,将交叉依赖中数据依赖源语句以及与交叉依赖数据依赖源语句交叉依赖的数据依赖目标语句从当前循环l移动到循环l+1中,若循环l+1不存在,则创建循环l+1,使交叉依赖转变为跨循环依赖,从而避免其对向量化的影响;若不存在交叉依赖,则结束。

具体如:以表2中交叉依赖d3为例,将其目标语句s3从第1个循环移动到第2个循环中,以消除交叉依赖d3。对于其他交叉依赖,也可采用类似的步骤消除。每消除一个交叉依赖,就更新一次依赖表,然后重新检查交叉依赖,直到代码中不存在交叉依赖。图2所示代码在完成语句重排后得到如图3所示的代码,并得到新的依赖表(表3)。

表3完成语句重排后的依赖表

验证过程和结果对比

本发明在intel(r)xeon(r)gold6140服务器上针对进行了实验验证,实验结果表明,本发明能够有效优化程序的向量化效率,并显著提升程序在向量处理器上的运行速度。

选择格子玻尔兹曼方法d3q19程序进行对比测试,采用intelc/c++编译器,与基线程序和pluto优化版本相比,本发明实现的开发潜在可向量化循环的方法使并行任务的向量化效率分别平均提高了292%和96%,将并行任务的执行速度分别平均提高了147%和120%。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1