CN105224452A - 一种针对科学计算程序静态分析性能的预测代价优化方法 - Google Patents
一种针对科学计算程序静态分析性能的预测代价优化方法 Download PDFInfo
- Publication number
- CN105224452A CN105224452A CN201510578802.5A CN201510578802A CN105224452A CN 105224452 A CN105224452 A CN 105224452A CN 201510578802 A CN201510578802 A CN 201510578802A CN 105224452 A CN105224452 A CN 105224452A
- Authority
- CN
- China
- Prior art keywords
- instruction
- function
- intermediate code
- mpi
- dependence
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Landscapes
- Devices For Executing Special Programs (AREA)
Abstract
一种针对科学计算程序静态分析性能的预测代价优化方法,本发明涉及针对科学计算程序静态分析性能的预测代价优化方法。本发明是要解决静态分析方法的预测代价大,引入误差的问题而提出的一种针对科学计算程序静态分析性能的预测代价优化方法。该方法是通过一、得到中间代码IR;步骤二、利用删减方法对中间代码IR进行依赖分析计算,得到依赖图;步骤三、利用剪枝方法的过滤函数将依赖图进行过滤,得到剪枝后的依赖图;步骤四、得到删除后的中间代码等步骤实现的。本发明应用于针对科学计算程序静态分析性能的预测代价优化方法领域。
Description
技术领域
本发明涉及预测代价优化方法,特别涉及一种针对科学计算程序静态分析性能的预测代价优化方法。
背景技术
传统的程序性能评测中,动态分析的方法是通过小规模预测大规模,即在小的输入规模和并行度下多次测量,将得到的数据绘制在一个坐标图上并进行曲线拟合或是回归分析,最后通过曲线拟合得到的公式,就能够预测更大规模和更大并行度下的运行时间,这种方法需要大量数据采样,预测代价非常大。而利用静态分析的方法,可以通过编译器阶段分析源代码直接获取程序的特征,然后再将分析后的程序特征插桩到原始程序中,对于编译阶段分析不出来的程序特征,通过插桩的方法在原始程序中获取,这种方法如果再选择运行插桩后的程序的话其预测代价也比较大,而且相对于动态分析的方法,还引入的静态分支概率等的误差,得不偿失。因此,需要一种方法,能够减少静态分析方法的预测代价,来弥补其不足。
发明内容
本发明的目的是为了解决静态分析方法的预测代价大,引入误差的问题而提出的一种针对科学计算程序静态分析性能的预测代价优化方法。
上述的发明目的是通过以下技术方案实现的:
步骤一、选择编译器框架LLVM对科学计算程序的编译成初始中间代码;将初始中间代码IR进行进行静态分析得到程序特征,将程序特征通过插桩的方法插入到初始中间代码后得到中间代码IR;
其中,中间代码为IR有三种格式:计算机内存中的编译中间语言、硬盘上存储的二进制中间语言和可读的中间语言;
步骤二、利用删减方法对中间代码IR进行依赖分析计算,得到依赖图;其中,依赖分析包括正向规则和反向规则;
步骤三、利用剪枝方法的过滤函数将依赖图进行过滤,得到剪枝后的依赖图;其中,过滤函数具体为:结构体过滤函数和调用过滤函数;
步骤四、根据调用关系CallGraph自下而上的方向遍历中间代码IR;结合剪枝后的依赖图中,在中间代码中删减代码时从fortran输出函数开始删除相关函数、相关函数对应的依赖指令、替换并行度参数、相关指令以及相关指令对应的依赖指令后,得到删除后的中间代码;
其中,相关函数包括fortran的输出函数、时间函数、MPI同步函数、MPI点对点通信函数、MPI汇集通信函数、MPI_Allreduce函数和MPI_Bcast函数;相关指令包括return指令和store指令。
发明效果
对于静态分析后的中间代码,我们首先通过基于规则的依赖分析(正向规则和反向规则的组合),生成指令的依赖图;然后通过过滤方法对依赖图进行剪枝,减少图的规模,提高处理速度;做了以上两步工作之后,我们就可以删减代码,这样就打开了依赖关系,把删减的指令和其依赖的指令一起删除掉;进而通过编译器死代码消除的方法删减更多的无用指令;最后编译成可执行程序。该程序由于是删减代码之后的程序,因此执行时间大大的缩短,由于又删除的mpi指令,因此可以在单机运行,很好的实现了单机模拟多机如图3。
由于一种针对科学计算程序静态分析性能的预测代价优化方法能自动的决定哪些语句是对插桩无用的,因此需要进行数据依赖关系分析。我们需要一个特殊的工具来辅助分析数据依赖问题。虽然LLVM的SSA形式直接揭示了一些在寄存器上的数据依赖关系,但对于内存依赖如load/store则无能为力。我们的目标是能找出load指令之前对应store语句,从而知道读取的内容是前面哪里写入的内容,亦即得到其依赖关系。
Use和User是LLVM的两个重要的概念。User是在定义时使用其他对象的复杂对象。所有指令都是User。如图7,Use是一个User和被使用对象的关系的二元组。Use的重要之处在于,对于一个对象%nblocks,LLVM能给出所有使用它的Use关系列表。并且迭代器use_begin位于IR的下方,use_end位于IR的商法。因此,我们需要利用Use列表来寻找依赖关系。
我们设计了DateDepGrap的数据结构来存储依赖关系,该数据结构是用HashMap来存储节点,std::vector来存储边(child),同时支持动态更新边和节点。例如一个树,存储为数据如图5所示,对每个节点都用一个数组来存储其子节点,这样,节点到各个子节点就表达了边的语义了。
由于静态分析过程已经通过分析源代码获取到程序的特征(基本块数量等),并将获取的数据插桩到原始程序中,原则上只需要保留插桩的代码,其他的如核心计算的代码就可以删除,这样就大大减少了该方法的性能预测代价。基于这种思想本发明实现了一种删减的方法,该方法能够确定程序中哪些语句是对插桩无用的,进而进行删除,减少程序的执行时间也就是预测代价,同时又能够获取程序特征,保证预测的准确性。
基于该结构,我们实现了一些工具,可以得到依赖关系图,如图6。其中反向规则是
下面将要介绍的概念。实现边框的是SOLVED的节点,表明被找到了有依赖的。虚线边框的是UNSOLVED的节点,表明被其他节点引用,但自身没有找出依赖的节点。
图11是基于EP(一个基准测试程序)的并行程序性能预测实验,其方法是通过静态分析并加入了删减的过程。横坐标为并行度,纵坐标为程序执行时间,可以看到,我们的预测代价是非常低的,而且不影响预测的准确性。达到了一种针对科学计算程序静态分析性能的预测代价优化方法的目的。
附图说明
图1为具体实施方式一提出的传统静态编译器结构示意图;
图2为具体实施方式一提出的LLVM编译器结构示意图;
图3为具体实施方式一提出的删减过程细节流程图;
图4为实施例一提出的删减原理示意图;
图5为具体实施方式一提出的一个树的DataDepGraph数据结构示意图;其中,1~6表示数据结构中的树的节点;
图6为具体实施方式一提出的一个利用反向规则查询的依赖关系写入的dot并转换成图片,其中,每一个矩形框中的内容表示的是一条中间代码指令;
图7为具体实施方式二提出的中间代码指令表示的直接依赖,同名依赖,User和Use的关系示意图;
图8为具体实施方式二提出的中间代码指令表示的正向规则查询gfortran输出语句的依赖关系图;
图9为具体实施方式五提出的一个函数调用图及其标记的数,其中,,function表示函数,a、b、c和d表示函数的名字;(1)~(6)、A~D表示划分的函数区域;call表示函数调用指令;
图10为具体实施方式一提出的Reduce运行层次结构示意图;
图11为实施例一提出的科学计算程序EP(EmbarrassinglyParallel)中的数据规模D在taub(大型集群环境)上的预测结果对比示意图。
具体实施方式
具体实施方式一:本实施方式的一种针对科学计算程序静态分析性能的预测代价优化方法,具体是按照以下步骤制备的:
所谓的规则是对于限定条件的输入才能应用相应的规则;我们并不设计一个固定的复杂的寻找依赖的过程函数,而是设计一个框架和一堆规则,通过将不同的规则组合进框架从而适应不同环境中寻找依赖的需求。
规则能够扩展图;例如,输入一条指令,通过查询匹配的规则,并应用之,则将此指令关联的其他指令加入进了依赖图中,每次一条匹配的规则将当前unsolve对象标记为solved,并加入更多的unsolve对象,从而下次执行循环的时候由popUnsolved返回,如此反复则不断的将图扩大。我们把这些规则分为正向规则和反向规则。
步骤一、选择编译器框架LLVM(LowLevelVirtualMachine)对科学计算程序的编译成初始中间代码;将初始中间代码IR进行进行静态分析(静态循环次数,静态分支概率等)得到程序特征(基本块次数等),将程序特征通过插桩的方法插入到初始中间代码后得到中间代码IR;
其中,中间代码为IR(IntermediateRepresentation)有三种格式:计算机内存中的编译中间语言、硬盘上存储的二进制中间语言(bitcode,即.bc文件)和可读的中间语言(.ll文件);三种格式完全等价,可以相互转换;LLVM的一大特色是设计了一套高度可用的中间代码,其语法类似汇编但比汇编更高级;
LLVM的编译器结构在传统编译器结构的基础上做了较大的改进;传统静态编译器分为前端、优化和后端三个阶段,前端对原程序进行分析并产生中间表示,后端在优化的中间表示基础上生成目标代码,结构如图1所示;LLVM结构如图2所示,这种结构的优点是如果需要支持一种新的编程语言,那么只需要实现一种新的前端;如果需要支持一种新的硬件设备,那只需要实现一个新的后端;而优化阶段因为是针对统一的LLVMIR,所以它是一个通用的阶段;
静态分析的优点就是不需要执行源程序就已经通过分析得到程序特征,但是还有一部分程序特征是不能通过编译器方法分析得到,比如,位于循环内的基本块,由于该循环的循环次数和程序内部的一些计算结果有关,这种情况下,就需要执行原始程序获取;而静态分析的方法引入了分支概率等的误差,如果再运行插桩后的程序的话就体现不出静态方法的优势,因此,我们加入删减模块来处理插桩后的程序;
科学计算程序是具有计算密集、高度并行和很少依赖第三方库等特点的并行处理程序;
步骤二、分析数据依赖关系,进而对无用的指令及其依赖进行删除;由于其对象是IR中间代码,因此可以支持多种高级语言的处理;利用删减方法对中间代码IR进行依赖分析计算,得到依赖图;其中,依赖分析包括正向规则和反向规则;
步骤三、在依赖的查询过程中,设计了过滤函数,过滤函数中除了能立即取得正在访问的内容外,还可以通过返回True(真)来将当前unsolved(未解决)对象标记为ignore(忽略)并停止继续搜索,由于依赖图是一个树状的图,返回True只能拒绝当前分支的搜索,其他分支还是会继续深入进去;因此利用剪枝方法的过滤函数将依赖图进行过滤以缩小依赖图的而规模,得到剪枝后的依赖图;其中,过滤函数具体为:结构体过滤函数和调用过滤函数;
通常能使得计算过程更快,最后的图更小,更能集中注意力在我们期望的内容上;那些预先设计好的回调函数即称为过滤(Filter),在查询过程中,优先应用所有的过滤函数,尽可能的提早剪枝;过滤函数通常需要一些参数来构造,因此使用时十分的方便;
步骤四、根据调用关系CallGraph自下而上的方向遍历中间代码IR;对每个调用关系节点CallGraphNode按自下而上的方向遍历;删除指令类型为fortran的输出函数、时间函数、MPI同步函数、MPI点对点通信函数、MPI汇集通信函数、MPI_Allreduce函数、MPI_Bcast函数、并行度参数、return指令和store指令;结合剪枝后的依赖图中,在中间代码中删减代码时从fortran输出函数开始删除相关函数、相关函数对应的依赖指令、替换并行度参数、相关指令以及相关指令对应的依赖指令后,得到删除后的中间代码;
先运行Reduce过程如图10,然后调用LLVM的instcombine和simpleCFG过程化简CFG图;最后,在每个函数内节点即基本块上,重复的应用Reduce过程和DSE适配器;直到发现该基本块中没有找到要删除的语句;
其中,相关函数包括fortran的输出函数、时间函数、MPI同步函数、MPI点对点通信函数、MPI汇集通信函数、MPI_Allreduce函数和MPI_Bcast函数;相关指令包括return指令和store指令。
本实施方式效果:
对于静态分析后的中间代码,我们首先通过基于规则的依赖分析(正向规则和反向规则的组合),生成指令的依赖图;然后通过过滤方法对依赖图进行剪枝,减少图的规模,提高处理速度;做了以上两步工作之后,我们就可以删减代码,这样就打开了依赖关系,把删减的指令和其依赖的指令一起删除掉;进而通过编译器死代码消除的方法删减更多的无用指令;最后编译成可执行程序。该程序由于是删减代码之后的程序,因此执行时间大大的缩短,由于又删除的mpi指令,因此可以在单机运行,很好的实现了单机模拟多机如图3。
由于一种针对科学计算程序静态分析性能的预测代价优化方法能自动的决定哪些语句是对插桩无用的,因此需要进行数据依赖关系分析。我们需要一个特殊的工具来辅助分析数据依赖问题。虽然LLVM的SSA形式直接揭示了一些在寄存器上的数据依赖关系,但对于内存依赖如load/store则无能为力。我们的目标是能找出load指令之前对应store语句,从而知道读取的内容是前面哪里写入的内容,亦即得到其依赖关系。
Use和User是LLVM的两个重要的概念。User是在定义时使用其他对象的复杂对象。所有指令都是User。如图7,Use是一个User和被使用对象的关系的二元组。Use的重要之处在于,对于一个对象%nblocks,LLVM能给出所有使用它的Use关系列表。并且迭代器use_begin位于IR的下方,use_end位于IR的商法。因此,我们需要利用Use列表来寻找依赖关系。
我们设计了DateDepGrap的数据结构来存储依赖关系,该数据结构是用HashMap来存储节点,std::vector来存储边(child),同时支持动态更新边和节点。例如一个树,存储为数据如图5所示,对每个节点都用一个数组来存储其子节点,这样,节点到各个子节点就表达了边的语义了。
由于静态分析过程已经通过分析源代码获取到程序的特征(基本块数量等),并将获取的数据插桩到原始程序中,原则上只需要保留插桩的代码,其他的如核心计算的代码就可以删除,这样就大大减少了该方法的性能预测代价。基于这种思想本实施方式实现了一种删减的方法,该方法能够确定程序中哪些语句是对插桩无用的,进而进行删除,减少程序的执行时间也就是预测代价,同时又能够获取程序特征,保证预测的准确性。
基于该结构,我们实现了一些工具,可以得到依赖关系图,如图6。其中反向规则是
下面将要介绍的概念。实现边框的是SOLVED的节点,表明被找到了有依赖的。虚线边框的是UNSOLVED的节点,表明被其他节点引用,但自身没有找出依赖的节点。
图11是基于EP(一个基准测试程序)的并行程序性能预测实验,其方法是通过静态分析并加入了删减的过程。横坐标为并行度,纵坐标为程序执行时间,可以看到,我们的预测代价是非常低的,而且不影响预测的准确性。达到了一种针对科学计算程序静态分析性能的预测代价优化方法的目的。
具体实施方式二:本实施方式与具体实施方式一不同的是:步骤二中正向规则的具体方法为:
1)利用直接依赖规则对中间代码IR进行依赖分析:
(1)利用直接依赖规则BaseRule在中间代码IR中寻找所有的SSA(StaticSingle-Assignment)依赖即直接依赖,并将直接依赖加入到依赖图中;
其中,SSA依赖具体为LLVM满足SSA形式的依赖;直接依赖规则BaseRule是正向规则中的必须的基础规则;因为LLVM满足SSA形式因此也称SSA依赖;
如图7,load指令直接依赖指针地址%nblocks;只要确定地址%nblocks,就能够保证读取出来的值是正确的;这里直接依赖并没有回答我们任何有价值信息;因此只有当其它规则都匹配失败了才会使用到直接依赖;同名依赖规则UseOnlyRule和结构体依赖规则GEPRule都未找到依赖关系才会使用到直接依赖;
(2)利用同名依赖的规则UseOnlyRule,将中间代码IR中的载入指令(load指令)及载入指令对应的最近的具有相同操作数的存储指令(load指令)加入依赖图;
如图7,同名依赖规则UseOnlyRule找出中间代码IR中的load指令(%15,%nblocks)及存储指令对应的最近的store指令(%9,%nblocks)加入到依赖图中,由于store指令存入的值为4,那么load指令得到的值就是4,因为store指令与load指令都是对应同一个操作数,所以将store指令与load指令称为同名依赖;其中,同名依赖算法如下:
(3)利用结构体依赖规则GEPRule寻找中间代码IR中的结构体数据或数组的依赖;找出结构体或数据对应的所有中间代码IR的getelementptr命令(该命令是llvmIR中的获取成员变量指针地址的指令),然后利用同名依赖规则UseOnlyRule查询结构体成员变量相应的store指令的依赖关系或数组与相应的store指令的依赖关系,并将依赖关系写入依赖图中;
如图8,查询getelementptr命令(call,%dt_param.10)的依赖关系,定义%dt_param.10是一个结构体;如果将结构体直接交给同名依赖去处理则会查询失败;因为是通过对结构体成员变量进行的写入操作,并没有结构体%dt_param.10的同名写操作;将%dt_param.10的所有getelementptr命令指令都作为unsolved去查询依赖关系,这样就再通过同名依赖能够将所有结构体的成员的存储操作都查询出来。其它步骤及参数与具体实施方式一相同。
具体实施方式三:本实施方式与具体实施方式一或二不同的是:步骤二中反向规则具体操作过程为:
(1)、利用直接引用规则确定中间代码IR中一条指令返回的变量,寻找出一条指令返回的变量对应的中间代码IR中使用变量的指令,确定一条指令和使用这条指令对应变量的指令的依赖关系,并将依赖关系加入到依赖图中;
其中,直接引用规则iBaseRule是反向规则中的基础规则,用于找出一个中间代码IR的变量;在图7中,%nblocks的直接引用就是迭代器use_begin和use_end之间的所有范围;而对于一个Use,其直接引用就是[Use.User.use_begin,Use.User.use_end];
(2)、利用后向引用规则iUseRule查询在中间代码IR中一条指令之后,判断是否有使用待查询变量的指令,如果没有使用待查询变量的指令,那么待查询变量对应的指令就可以被删除;如果有使用待查询变量的指令,那么保留待查询变量在依赖图中对应的指令
。其它步骤及参数与具体实施方式一或二相同。
具体实施方式四:本实施方式与具体实施方式一至三之一不同的是:步骤三中结构体过滤函数GEPFilter具体过程为:
(1)、在结构体依赖规则GEPRule中,将所有的结构体成员都加入未解决集合unsolved中;
(2)、过滤掉未解决集合unsolved中的结构体成员,保留标识fortran输出函数的成员;
例如在图8中,只关注对结构体成员(0,0,1)的store操作;通过是否是写入fortran确定的6来判断是否是fortran的输出语句(即fortran的输出函数);GEPFilter可以获取结构体成员(0,0,1)的值,判断结构体成员(0,0,1)的值是否是6,如果是的话则返回False(放行),不过不是的话则返回True(过滤)。其它步骤及参数与具体实施方式一至三之一相同。
具体实施方式五:本实施方式与具体实施方式一至四之一不同的是:步骤三中调用过滤函数CGFilter具体为:1)利用调用关系CallGraph信息计算中间代码的相同函数的指令的偏序关系;
(1)、根据调用关系CallGraph获取中间代码的相同函数的指令的遍历顺序;
(2)、利用相同函数中两条指令的偏序关系算法(less<Instruction>),结合中间代码中的相同函数的指令的遍历顺序求出每条指令分别到begin()迭代器的距离,并将距离从小到大升序排列;得到中间代码的相同函数的指令的偏序关系;
这类似于use_begin/use_end也是IR自然排序;但Use关系只是针对同名对才有效,而指令偏序对于所有指令都有效;若i在j之前,记以中间代码的基本块BasicBlock的IR中的指令的升序排序计算方法:
作i<j;
2)根据相同函数的偏序关系和两个不同函数在中间代码IR中的位置关系,确定不同函数的指令的偏序关系;
(1)利用LLVM提供的深度遍历迭代器将中间代码IR中每个函数按照区块进行划分,得到一组函数对应的中间代码中的指令映射到函数的正数序列;
(2)如果中间代码中的指令映射到函数的正数序列上,函数的正数序列上任意两条指令映射中的任意一个正数相同,则这两条指令属于同一个函数,利用相同函数中两条指令偏序关系算法(less<Instrunction>)来获取偏序关系,如果任意两条指令映射的正数不同,则直接比较正数的大小来获取偏序关系;
通常偏序关系用于回答一个全局变量在指定位置之后是否还被使用;
例如图9如果对于某个函数如a中的两条指令,可以直接利用less<Instruction>得到偏序,但是对于b中的任意指令l和d中任意指令r,实际上根据CallGraph,b在d之前执行,于是得到l<r,因此若l指令类似于对全局变量的写入,则可能会影响r中的读取;类似的还有b中的指令l和e中的指令r,在不同的情况下有l<r或者l>r;求偏序关系,对指令排序;即通过将指令映射到正数序列上再进行比较即可得到偏序;需要保证若映射的整数相同则其所在的函数也相同,这样可以方便地降级到上面less<Instruction>的情况;若映射不同则能通过直接比较大小求偏序;图9将每个函数按照区块划分,得到的正数序列标注在括号中;
每一个函数对应一个调用关系节点CallGraphNode,设定函数用一个小写字母表示,函数中的某个区域用大写字母表示;扩号内的是标记的序列用一个半开半闭区间[first,last]来表示其内的映射范围,例如indexof(a)=[0,9]indexof(c)=[4,5],indexof(b)=[1,6]对于calle这条指令,设它小于函数e中的所有指令,即indexof(calle)=indexof(e).first-1设func(call)为求call指令对应的函数的对于D中的指令,映射为3,寻找同函数中满足call_1<D<call_2,因此有indexof(D)=indexof(call_2)=indexof(func(call_2)).first-1,或者indexof(D)=indexof(func(call_1)).last;这里call_2=callc,即indexof(D)=indexof(c).first-1=4-1=3最后,如果同函数中找不到比指令更大的call,即它在函数的最末尾,如C,那么有indexof(C)=indexof(c).last=5,也可以用indexof(C)=indexof(b).last-1=5;如果同函数中找不到比它更小的call,即它在函数的最开始,那么它直接等于所在的函数的index即可;
对于特例A,由于其下的callc是重复调用的,早在之前就计算出了c的index为4,所以这里对于那些重复调用的call所采取的做法是直接忽略,即属于A的一部分;因此callc的index等于A的index;当它不存在;因此计算A的时候call_2=calld,无论是用第一个计算公式还是第二个,都同样计算出得到6;使用一个Only集合来储存那些第一次访问到的call指令(即不在该集合中的都是重复的);
查询时,都假设它尽可能的提前调用,例如我们查询c函数中某条指令是否小于A,应当返回True,因为它可能是发生在D和C之间的那条call语句,因此它是可能会影响到A的;而对于A和B的两条指令,他们的index相同,事实上理解的时候也可以把他们作为一个整体来看的,可以直接用less<Instruction>比较;
所以现在问题主要集中在如何确定每个函数的区间范围,由于需要使用LLVM的深度遍历迭代器,因此7个函数只会调用7次,不可能在其中同时完成计算进入函数和退出函数的操作;于是我们决定首先推算出每个函数的first,然后再用一次后序遍历推算出每个函数的last;
深度遍历的顺序是注意到进入函数都是增加1,在同函数中都是增加2(退出一次+1,进入一次+1),退出函数都是+1,c->d中是先退出2次再进入1次;深度遍历的时候只能取得遍历当前深度信息,利用该信息我们可以得到indexOf[C].first=indexOf[C-1].first+L-1-L+2这样的公式,L-1表示上个访问节点的深度,C-1表示上个访问的节点,a的深度为1;a的index为0,带入公式得到0=indexOf[C-1].first+L-1+1,令初始值L-1=0,则有初始值indexOf[C-1].first=-1;
有了first,计算last则非常简单,如果C为叶节点,则last=first+1,否则C中最后一个孩子节点的last+1即可,last=last[child[C]].last+1;
。其它步骤及参数与具体实施方式一至四之一相同。
具体实施方式六:本实施方式与具体实施方式一至五之一不同的是:步骤四中删除的fortran的输出函数具体为:
删减代码时从fortran输出函数开始,由于MPI的科学计算程序大多用fortran语言写成,所以这里主要针对fortran来处理,当删掉fortran输出语句之后,LLVM的死代码消除能清除掉fortran输出函数对应的依赖指令store语句和getelementptr语句。其它步骤及参数与具体实施方式一至五之一相同。
具体实施方式七:本实施方式与具体实施方式一至六之一不同的是:步骤四中删除的时间函数为MPI的mpi_wtime_和_gfortran_system_clock_4;时间函数为不参与运算的fortran输出统计时间的;所以可以直接删掉;级联删除时间函数和时间函数对应的依赖指令即fortran输出统计时间的指令。其它步骤及参数与具体实施方式一至六之一相同。
具体实施方式八:本实施方式与具体实施方式一至七之一不同的是:步骤四中删除的MPI同步函数具体为控制科学计算程序进程通信的过程的函数,最后都会将MPI调用删除干净。其它步骤及参数与具体实施方式一至七之一相同。
具体实施方式九:本实施方式与具体实施方式一至八之一不同的是:步骤四中替换并行度参数包括的MPI中的变量mpi_comm_size_和mpi_comm_rank为重要的替换并行度参数;mpi_comm_size_用于获取并行度规模和mpi_comm_rank用于标识科学计算程序的进程号,在删减代码之后输入重要参数mpi_comm_size_和重要参数mpi_comm_rank;
其中,mpi_comm_size替换成设置环境变量MPI_SIZE传入mpi_comm_size值的代码和mpi_comm_rank替换成设置环境变量MPI_RANK传入mpi_comm_rank值的代码。其它步骤及参数与具体实施方式一至八之一相同。
具体实施方式十:本实施方式与具体实施方式一至九之一不同的是:步骤四中return指令是将函数计算结果从函数中返回,这样return指令会阻碍计算部分的中间代码删除,因此,删除的return指令具体为删除所有调用函数都没有使用函数返回值的return指令。其它步骤及参数与具体实施方式一至九之一相同。
采用以下实施例验证本发明的有益效果:
实施例一:
本实施例一种针对科学计算程序静态分析性能的预测代价优化方法,具体是按照以下步骤制备的:
一种针对科学计算程序静态分析性能的预测代价优化方法类似于优化中的消除死代码,但这里创新之处在于所有的优化过程都是基于语义的等价变换,需要保证最后的结果一致。但删除是激进的破坏性的优化,因为我们只需要使得程序特征即循环次数信息不被破坏,其它的信息对我们而言都变成了‘死代码’一般。因为这点,我们能够做得比编译器自带的优化更多更远。我们选择删除法来消除‘死代码’,首先选择一些没有被使用的、可以被删除的语句,由于该语句还依赖其它语句。当删除后,就打开了依赖关系。因而那些语句变成了未被使用语句,于是也是可以被删除的。如此反复递归下去,直到删除干净。
如图4,一般程序的执行过程都分为初始化、计算、输出三部分。因为程序特征是由静态分析获取,而插桩之后的程序输出结果是不重要的,因此我们首先能够确定输出语句是不重要的,由于它只是显示信息,不会影响循环次数即程序特征,因此可以被安全的删除。由于现在程序已经不再将计算结果输出了,那计算结果也就变成未使用的了,因而同样可以删除了。而当没有了计算结果,那计算过程也就无意义了,因而计算过程也可以被删除。最后一个程序被删除得只剩下初始化语句和插桩语句,没有了整个计算部分,因而其运行速度会大大提高。
由于删减了一部分代码,使得程序内部结构松散,比如一些死代码等等,很多可以被再次优化。因此我们进行一个可选的编译器O3优化,以进一步的压缩程序的执行时间。
图11是基于EP(一个基准测试程序)的并行程序性能预测实验,其方法是通过静态分析并加入了删减的过程。横坐标为并行度,纵坐标为程序执行时间,可以看到,我们的预测代价是非常低的,而且不影响预测的准确性。达到了一种针对科学计算程序静态分析性能的预测代价优化方法的目的。
本发明还可有其它多种实施例,在不背离本发明精神及其实质的情况下,本领域技术人员当可根据本发明作出各种相应的改变和变形,但这些相应的改变和变形都应属于本发明所附的权利要求的保护范围。
Claims (10)
1.一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于一种针对科学计算程序静态分析性能的预测代价优化方法具体是按照以下步骤进行的:
步骤一、选择编译器框架LLVM对科学计算程序的编译成初始中间代码;将初始中间代码IR进行进行静态分析得到程序特征,将程序特征通过插桩的方法插入到初始中间代码后得到中间代码IR;
其中,中间代码为IR有三种格式:计算机内存中的编译中间语言、硬盘上存储的二进制中间语言和可读的中间语言;
步骤二、利用删减方法对中间代码IR进行依赖分析计算,得到依赖图;其中,依赖分析包括正向规则和反向规则;
步骤三、利用剪枝方法的过滤函数将依赖图进行过滤,得到剪枝后的依赖图;其中,过滤函数具体为:结构体过滤函数和调用过滤函数;
步骤四、根据调用关系CallGraph自下而上的方向遍历中间代码IR;结合剪枝后的依赖图中,在中间代码中删减代码时从fortran输出函数开始删除相关函数、相关函数对应的依赖指令、替换并行度参数、相关指令以及相关指令对应的依赖指令后,得到删除后的中间代码;
其中,相关函数包括fortran的输出函数、时间函数、MPI同步函数、MPI点对点通信函数、MPI汇集通信函数、MPI_Allreduce函数和MPI_Bcast函数;相关指令包括return指令和store指令。
2.根据权利要求1所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤二中正向规则的具体方法为:
1)利用直接依赖规则对中间代码IR进行依赖分析:
(1)利用直接依赖规则BaseRule在中间代码IR中寻找所有的SSA依赖即直接依赖,并将直接依赖加入到依赖图中;
其中,SSA依赖具体为LLVM满足SSA形式的依赖;直接依赖规则BaseRule是正向规则中的必须的基础规则;
(2)利用同名依赖的规则UseOnlyRule,将中间代码IR中的载入指令及载入指令对应的最近的具有相同操作数的存储指令加入依赖图;
(3)利用结构体依赖规则GEPRule寻找中间代码IR中的结构体数据或数组的依赖;找出结构体或数据对应的所有中间代码IR的命令,利用同名依赖规则UseOnlyRule查询结构体成员变量相应的store指令的依赖关系或数组与相应的store指令的依赖关系,并将依赖关系写入依赖图中。
3.根据权利要求2所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤二中反向规则具体操作过程为:
(1)、利用直接引用规则确定中间代码IR中一条指令返回的变量,寻找出一条指令返回的变量对应的中间代码IR中使用变量的指令,确定一条指令和使用这条指令对应变量的指令的依赖关系,并将依赖关系加入到依赖图中;
(2)、利用后向引用规则iUseRule查询在中间代码IR中一条指令之后,判断是否有使用待查询变量的指令,如果有使用待查询变量的指令,那么保留待查询变量在依赖图中对应的指令。
4.根据权利要求3所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤三中结构体过滤函数GEPFilter具体过程为:
(1)、在结构体依赖规则GEPRule中,将所有的结构体成员都加入未解决集合中;
(2)、过滤掉未解决集合unsolved中的结构体成员,保留标识fortran输出函数的成员。
5.根据权利要求4所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤三中调用过滤函数CGFilter具体为:
1)利用调用关系CallGraph信息计算中间代码的相同函数的指令的偏序关系;
(1)、根据调用关系CallGraph获取中间代码的相同函数的指令的遍历顺序;
(2)、利用相同函数中两条指令的偏序关系算法,结合中间代码中的相同函数的指令的遍历顺序求出每条指令分别到迭代器的距离,并将距离从小到大升序排列;得到中间代码的相同函数的指令的偏序关系;
2)根据相同函数的偏序关系和两个不同函数在中间代码IR中的位置关系,确定不同函数的指令的偏序关系;
(1)利用LLVM提供的深度遍历迭代器将中间代码IR中每个函数按照区块进行划分,得到一组函数对应的中间代码中的指令映射到函数的正数序列;
(2)如果中间代码中的指令映射到函数的正数序列上,函数的正数序列上任意两条指令映射中的任意一个正数相同,则这两条指令属于同一个函数,利用相同函数中两条指令偏序关系算法来获取偏序关系,如果任意两条指令映射的正数不同,则直接比较正数的大小来获取偏序关系。
6.根据权利要求5所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤四中删除的fortran的输出函数具体为:
删减代码时从fortran输出函数开始,当删掉fortran输出语句之后,LLVM的死代码消除能清除掉fortran输出函数对应的依赖指令store语句和getelementptr语句。
7.根据权利要求6所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤四中删除的时间函数为MPI的mpi_wtime_和_gfortran_system_clock_4;时间函数为不参与运算的fortran输出统计时间的;级联删除时间函数和时间函数对应的依赖指令。
8.根据权利要求7所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤四中删除的MPI同步函数具体为控制科学计算程序进程通信的过程的函数。
9.根据权利要求8所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤四中替换并行度参数包括的MPI中的变量mpi_comm_size_和mpi_comm_rank为重要的替换并行度参数;mpi_comm_size_用于获取并行度规模和mpi_comm_rank用于标识科学计算程序的进程号,在删减代码之后输入重要参数mpi_comm_size_和重要参数mpi_comm_rank;
其中,mpi_comm_size替换成设置环境变量MPI_SIZE传入mpi_comm_size值的代码和mpi_comm_rank替换成设置环境变量MPI_RANK传入mpi_comm_rank值的代码。
10.根据权利要求9所述一种针对科学计算程序静态分析性能的预测代价优化方法,其特征在于:步骤四中删除的return指令具体为删除所有调用函数都没有使用函数返回值的return指令。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201510578802.5A CN105224452B (zh) | 2015-09-11 | 2015-09-11 | 一种针对科学计算程序静态分析性能的预测代价优化方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201510578802.5A CN105224452B (zh) | 2015-09-11 | 2015-09-11 | 一种针对科学计算程序静态分析性能的预测代价优化方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN105224452A true CN105224452A (zh) | 2016-01-06 |
CN105224452B CN105224452B (zh) | 2018-03-16 |
Family
ID=54993437
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201510578802.5A Active CN105224452B (zh) | 2015-09-11 | 2015-09-11 | 一种针对科学计算程序静态分析性能的预测代价优化方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN105224452B (zh) |
Cited By (10)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN109002713A (zh) * | 2018-06-26 | 2018-12-14 | 中国科学院计算技术研究所 | 安全规则检测方法和系统 |
CN109062784A (zh) * | 2018-07-06 | 2018-12-21 | 北京大学 | 接口参数约束代码入口定位方法与系统 |
CN109710419A (zh) * | 2018-11-13 | 2019-05-03 | 北京航空航天大学 | 基于文本分析的mpi代码通信过程解析方法 |
CN110377525A (zh) * | 2019-07-25 | 2019-10-25 | 哈尔滨工业大学 | 一种基于运行时特征和机器学习的并行程序性能预测系统 |
CN111768229A (zh) * | 2020-06-23 | 2020-10-13 | 北京思特奇信息技术股份有限公司 | 一种基于卡券的前向规则控制系统 |
CN112541188A (zh) * | 2019-09-20 | 2021-03-23 | 武汉斗鱼网络科技有限公司 | 阻止应用程序代码被静态分析的方法及装置 |
CN113051004A (zh) * | 2021-03-30 | 2021-06-29 | 北京字节跳动网络技术有限公司 | 一种依赖函数的处理方法、装置、设备及存储介质 |
CN114327789A (zh) * | 2022-01-07 | 2022-04-12 | 北京大学 | 一种基于llvm的虚拟机保护方法及系统 |
CN114817061A (zh) * | 2022-05-16 | 2022-07-29 | 厦门大学 | 虚拟构建脚本的依赖性错误检测方法 |
CN115292203A (zh) * | 2022-09-30 | 2022-11-04 | 平安银行股份有限公司 | 一种源代码分析方法及装置 |
Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101286132A (zh) * | 2008-06-02 | 2008-10-15 | 北京邮电大学 | 一种基于软件缺陷模式的测试方法及系统 |
WO2010070490A1 (en) * | 2008-12-18 | 2010-06-24 | Koninklijke Philips Electronics, N.V. | Software bug and performance deficiency reporting system |
-
2015
- 2015-09-11 CN CN201510578802.5A patent/CN105224452B/zh active Active
Patent Citations (2)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN101286132A (zh) * | 2008-06-02 | 2008-10-15 | 北京邮电大学 | 一种基于软件缺陷模式的测试方法及系统 |
WO2010070490A1 (en) * | 2008-12-18 | 2010-06-24 | Koninklijke Philips Electronics, N.V. | Software bug and performance deficiency reporting system |
Non-Patent Citations (1)
Title |
---|
谢虎成: "基于LLVM的科学计算程序自动性能预测研究", 《中国知网》 * |
Cited By (13)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN109002713A (zh) * | 2018-06-26 | 2018-12-14 | 中国科学院计算技术研究所 | 安全规则检测方法和系统 |
CN109062784A (zh) * | 2018-07-06 | 2018-12-21 | 北京大学 | 接口参数约束代码入口定位方法与系统 |
CN109710419A (zh) * | 2018-11-13 | 2019-05-03 | 北京航空航天大学 | 基于文本分析的mpi代码通信过程解析方法 |
CN110377525A (zh) * | 2019-07-25 | 2019-10-25 | 哈尔滨工业大学 | 一种基于运行时特征和机器学习的并行程序性能预测系统 |
CN112541188B (zh) * | 2019-09-20 | 2022-05-13 | 武汉斗鱼网络科技有限公司 | 阻止应用程序代码被静态分析的方法及装置 |
CN112541188A (zh) * | 2019-09-20 | 2021-03-23 | 武汉斗鱼网络科技有限公司 | 阻止应用程序代码被静态分析的方法及装置 |
CN111768229A (zh) * | 2020-06-23 | 2020-10-13 | 北京思特奇信息技术股份有限公司 | 一种基于卡券的前向规则控制系统 |
CN111768229B (zh) * | 2020-06-23 | 2023-10-13 | 北京思特奇信息技术股份有限公司 | 一种基于卡券的前向规则控制系统 |
CN113051004A (zh) * | 2021-03-30 | 2021-06-29 | 北京字节跳动网络技术有限公司 | 一种依赖函数的处理方法、装置、设备及存储介质 |
CN114327789A (zh) * | 2022-01-07 | 2022-04-12 | 北京大学 | 一种基于llvm的虚拟机保护方法及系统 |
CN114327789B (zh) * | 2022-01-07 | 2024-05-17 | 北京大学 | 一种基于llvm的虚拟机保护方法及系统 |
CN114817061A (zh) * | 2022-05-16 | 2022-07-29 | 厦门大学 | 虚拟构建脚本的依赖性错误检测方法 |
CN115292203A (zh) * | 2022-09-30 | 2022-11-04 | 平安银行股份有限公司 | 一种源代码分析方法及装置 |
Also Published As
Publication number | Publication date |
---|---|
CN105224452B (zh) | 2018-03-16 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
CN105224452A (zh) | 一种针对科学计算程序静态分析性能的预测代价优化方法 | |
US9864590B2 (en) | Method and system for automated improvement of parallelism in program compilation | |
US8930919B2 (en) | Modernization of legacy software systems based on modeled dependencies | |
EP3572952A1 (en) | Unified optimization of iterative analytical query processing | |
US20080082969A1 (en) | Software Testing Technique Supporting Dynamic Data Structures | |
CN111104335B (zh) | 一种基于多层次分析的c语言缺陷检测方法及装置 | |
CN113641701B (zh) | 一种数据查询方法、系统、异构加速平台及存储介质 | |
JP2001166949A (ja) | シンボリック実行を用いてソースコードをコンパイルするための方法及び装置 | |
EP3465428A1 (en) | Sample driven profile guided optimization with precise correlation | |
US20100250564A1 (en) | Translating a comprehension into code for execution on a single instruction, multiple data (simd) execution | |
US5396627A (en) | Method of producing object program based on interprocedural dataflow analysis of a source program | |
Zheng et al. | Fusionstitching: boosting memory intensive computations for deep learning workloads | |
US20130060753A1 (en) | Optimization Method And Apparatus | |
Fan et al. | Graph algorithms: parallelization and scalability | |
Novillo | Samplepgo-the power of profile guided optimizations without the usability burden | |
CN115809063A (zh) | 一种存储过程编译方法、系统、电子设备和存储介质 | |
CN116301755A (zh) | 一种基于有向计算图的自动化批流数据打标框架构建方法 | |
Putta et al. | Parallel replication-based points-to analysis | |
US10268461B2 (en) | Global data flow optimization for machine learning programs | |
CN113553054A (zh) | 基于异构系统的编译方法、装置、设备及存储介质 | |
Chiba et al. | Towards selecting best combination of sql-on-hadoop systems and jvms | |
CN112527304B (zh) | 基于异构平台的自适应节点融合编译优化方法 | |
US20210042099A1 (en) | Automatic generation of efficient vector code with low overhead in a time-efficient manner independent of vector width | |
US20230116546A1 (en) | Method for compilation, electronic device and storage medium | |
Ma et al. | Parallel exact inference on multicore using mapreduce |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
C06 | Publication | ||
PB01 | Publication | ||
C10 | Entry into substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |