用于稀疏矩阵的自动重新排序的技术的制作方法

文档序号:11216248阅读:858来源:国知局
用于稀疏矩阵的自动重新排序的技术的制造方法与工艺



背景技术:

稀疏数据结构(诸如图和稀疏矩阵)上的高性能计算(hpc)在例如包含机器学习、计算科学、物理模型模拟、web搜索以及知识发现的广泛领域中正在变得越来越重要。传统高性能计算应用一般涉及规则和密集数据结构;然而,稀疏计算具有某些独一无二的挑战。例如,稀疏计算通常比密集计算具有低得多的计算密度,并且因此,其性能经常受存储带宽的限制。此外,存储器存取模式和并行度的量变化很大,例如取决于输入数据的特定稀疏度模式,这使优化复杂化了,因为某些优化信息经常是未知的先验。

系统可修改输入数据集以获得高数据局部性,以便处理那些挑战。例如,系统可采用重新排序,其置换矩阵的行和/或列以便集群彼此附近的非零项。例如,系统可重新排序稀疏矩阵100以生成带状矩阵102,其中非零项104在彼此附近群集,如图1a-b所示的。通过这么做,系统增大了具体存储器读取涉及更多非零项(即空间局部性)的机会,并且可导致比没有重新排序在高速缓存当中更多的再用(即时间局部性)。已经开发并实现了各种重新排序算法,例如包含广度优先搜索(bfs)、反向cuthill-mckee(rcm)、自回避行走(saw)、metis划分器和king's算法。具体地说,bfs及其更精细版本rcm由于其较小的复杂性和较大的效率而被频繁用于优化稀疏矩阵向量乘法(spmv)中的高速缓存局部性。

附图说明

本文描述的概念在附图中作为示例而非作为限制图示。为了图示的简洁和清晰起见,在附图中图示的元件不一定按比例绘制。视情况而定,附图标记在图之间已经被重复了以指示对应或类似元件。

图1a是稀疏矩阵的至少一个实施例的简化图解;

图1b是重新排序的稀疏矩阵的至少一个实施例的简化图解;

图2是用于稀疏矩阵的自动重新排序的计算装置的至少一个实施例的简化框图;

图3是图2的计算装置的环境的至少一个实施例的简化框图;

图4a是程序代码段的至少一个实施例;

图4b-4c是图4a的程序代码段的重新排序版本的实施例;

图5是可由图2的计算装置执行的用于稀疏矩阵的自动重新排序的方法的至少一个实施例的简化流程图;

图6是可由图2的计算装置执行的用于执行相互依赖的阵列(array)分析的方法的至少一个实施例的简化流程图;

图7a是表达式(expression)树的至少一个实施例的简化图解;

图7b是根据图7a的表达式树生成的表达式子树的集合的至少一个实施例的简化图解;

图8是可由图2的计算装置执行的用于执行双向数据流分析的方法的至少一个实施例的简化流程图;

图9是来自应用双向分析以便发现可重新排序阵列的结果的至少一个实施例的部分表;

图10是代码区域中程序代码的简化框图;

图11是来自向图10的程序代码应用没有优化的双向分析的结果的至少一个实施例的部分表;

图12是基于图11的没有优化的双向分析的结果的图10的程序代码的重新排序版本的简化框图;

图13是来自基于活性向图10的程序代码应用没有优化的双向分析的结果的至少一个实施例的部分表;

图14是基于图13的基于活性的具有优化的双向分析的结果的图10的程序代码的重新排序版本的简化框图;

图15是来自基于执行频率向图10的程序代码应用具有优化的双向分析的结果的至少一个实施例的部分表;

图16是基于图15的基于执行频率的具有优化的双向分析的结果的图10的程序代码的重新排序版本的简化框图。

具体实施方式

虽然本公开的概念易受到各种修改和备选形式,但其特定实施例已经在附图中作为示例示出,并且将在本文中详细描述。然而,应该理解,没有意图将本公开的概念局限于所公开的具体形式,而是相反,本发明要覆盖与本公开和所附权利要求书一致的所有修改、等效方案和备选。

在说明书中提到“一个实施例”、“实施例”、“图示实施例”等指示所描述的实施例可包含具体特征、结构或特性,但每一个实施例可以或者可以不必需包含该具体特征、结构或特性。而且,此类短语不一定是指同一实施例。进一步说,当具体特征、结构或特性结合实施例进行描述时,认为它在本领域技术人员的认知之内,以结合其它实施例实现此类特征、结构或特性,不管是否明确描述了。此外,应该认识到,包含在以“a、b和c中的至少一个”的形式的列表中的术语可意味着(a);(b);(c);(a和b);(b和c);(a和c)或(a,b和c)。类似地,包含在以“a、b或c中的至少一个”形式的列表中的术语可意味着(a);(b);(c);(a和b);(b和c);(a和c)或(a,b和c)。

所公开的实施例在一些情况下可用硬件、固件、软件或它们的任何组合来实现。所公开的实施例也可实现为由一个或多个暂时性或非暂时性机器可读(例如计算机可读)存储介质携带或存储在其上的指令,其可由一个或多个处理器读取和执行。机器可读存储介质可实施为用于存储或传输由机器(例如易失性或非易失性存储器、媒体盘或其它媒体装置)可读形式的信息的任何存储装置、机制或其它物理结构。

在附图中,一些结构或方法特征可按特定布置和/或排序示出。然而,应该认识到,可能不需要此类特定布置和/或排序。而是,在一些实施例中,此类特征可按与在说明性附图中示出的不同的方式和/或次序布置。此外,在具体附图中包含结构或方法特征不打算暗示此类特征在所有实施例中都需要,并且在一些实施例中,可能不被包含或者可与其它特征组合。

现在参考图2,示出了用于稀疏矩阵的自动重新排序的计算装置200。如下面所详细描述的,计算装置200配置成将本文描述的一个或多个算法自动应用于任意重新排序函数(例如用于加速稀疏内核的执行)以自动确定重新排序是否对任意函数都可应用/可准许,并且如果是,则施加一个或多个算法,无需改变一个或多个基础表达式的语义。应该认识到,此类自动重新排序技术甚至可改进专家编程人员的能力和/或效率,例如通过消除或减少对于人工重新排序优化的需要,其经常是易错的并且耗时的过程。在说明性实施例中,计算装置200通过如下方式确定重新排序的可行性:确认所关注的具体代码区域中的语句是分布性的,并且如果是这样,则识别在代码区域之前、之后和/或之内的要重新排序和/或反向重新排序的一个或多个阵列(例如多维矩阵和/或一维向量),使得代码区域外部的代码不受重新排序影响。

计算装置200可被实施为能够执行本文描述的功能的任何类型计算装置或系统。例如,在一些实施例中,计算装置200可被实施为桌上型计算机、膝上型计算机、平板计算机、笔记本、上网本、ultrabook™、智能电话、蜂窝电话、可穿戴计算装置、个人数字助理、移动因特网装置、智能装置、服务器、路由器、交换机、混合装置和/或任何其它计算/通信装置。如图2中所示,说明性计算装置200包含处理器210、输入/输出("i/o")子系统212、存储器214、数据存储装置216、通信电路118和一个或多个外围装置220。当然,在其它实施例中,计算装置200可包含其它或附加组件,诸如通常在典型计算装置(例如各种输入/输出装置和/或其它组件)中发现的那些。此外,在一些实施例中,说明性组件的一个或多个可结合在另一组件中,或以其它方式形成另一组件的一部分。例如,在一些实施例中,存储器214或其部分可被结合在处理器210中。

处理器210可被实施为能够执行本文描述的功能的任何类型处理器。例如,处理器210可实施为单核或多核处理器(一个或多个)、数字信号处理器、微控制器或其它处理器或处理/控制电路。类似地,存储器214可实施为能够执行本文描述的功能的任何类型易失性或非易失性存储器或数据存储装置。在操作中,存储器214可存储在计算装置200操作期间使用的各种数据和软件,诸如操作系统、应用、程序、库以及驱动程序。存储器214以通信方式经由i/o子系统212耦合到处理器210,i/o子系统可实施为电路和/或组件以促进与计算装置200的处理器210、存储器214和/或其它组件的输入/输出操作。例如,i/o子系统212可实施为或以其它方式包含存储器控制器集线器、输入/输出控制集线器、固件装置、通信链路(即,点对点链路、总线链路、导线、电缆、光导、印刷电路板迹线等)和/或其它组件和子系统以促进输入/输出操作。在一些实施例中,i/o子系统212可形成片上系统(soc)的一部分,并与计算装置200的处理器210、存储器214和其它组件一起结合在单个集成电路芯片上。

数据存储装置216可实施为配置用于数据的短期存储或长期存储的任何类型装置(一个或多个),诸如例如存储器件和电路、存储卡、硬盘驱动器、固态驱动器或其它数据存储装置。数据存储装置216和/或存储器214可在如本文所描述的计算装置200的操作期间存储各种数据。

通信电路218可实施为能够实现通过网络在计算装置200与其它移动装置之间通信的任何通信电路、装置或它们的集成。例如,在一些实施例中,计算装置200可从远程计算装置接收用户程序、要重新排序的第一阵列(far)的身份和/或用于执行本文描述的函数的其它有用数据。通信电路218可配置成使用任一个或多个通信技术(例如无线或有线通信)以及关联的协议(例如以太网、bluetooth®、wi-fi®、wimax、lte、5g等)来实现此类通信。

外围装置220可包含任何数量的传统外围装置或接口装置,诸如扬声器、麦克风、附加存储装置等。包含在外围装置220中的具体装置例如可取决于计算装置200的类型和/或预期用途。

现在参考图3,在使用中,计算装置200建立用于稀疏矩阵的自动重新排序的环境300。说明性环境300包含区域标识模块302、分布性分析模块304、活性分析模块306、相互依赖的阵列分析模块308、可重新排序阵列发现模块310和代码变换模块312。环境300的各种模块可实施为硬件、软件、固件或它们的组合。例如,环境300的各种模块、逻辑和其它组件可形成处理器210或计算装置200的其它硬件组件的一部分,或者以其它方式由其建立。像这样,在一些实施例中,环境300的一个或多个模块可实施为电路或电气装置的集合(例如标识电路302、分布性分析电路304、活性分析电路306、相互依赖的阵列分析电路308、可重新排序阵列发现电路310和/或代码变换电路312)。应该认识到,在此类实施例中,标识电路302、分布性分析电路304、活性分析电路306、相互依赖的阵列分析电路308、可重新排序阵列发现电路310和/或代码变换电路312中的一个或多个可形成处理器210、i/o子系统212、存储器214、数据存储装置216、通信电路218和/或外围装置220中的一个或多个的一部分。此外,在一些实施例中,说明性模块的一个或多个可形成另一模块的一部分,和/或说明性模块的一个或多个可彼此独立。如图3所示的,在一些实施例中,环境300的各种模块的一个或多个可形成计算装置200的编译器314的一部分,或由其执行。

如本文所描述的,计算装置200配置成例如向程序的代码区域施加重新排序变换以便改进程序的执行时间。区域标识模块302配置成识别要分析的代码区域以便重新排序。应该认识到,代码区域可以是任意表达式、块、语句、语句/指令的集合/序列和/或程序的另一部分。例如,在一些实施例中,代码区域可包含顺序语句、循环语句(例如“for”、“repeat...until”、“while”等)、流控制语句(例如,“if...else”、“goto”、“break”、“exit”等)和/或其它语句。更确切地说,在一些实施例中,区域标识模块302选择不包含流语句作为代码区域的线性循环区域。另外,在一些实施例中,区域标识模块302可选择其中程序花费了大量其执行时间(例如至少持续阈值时间段、至少持续阈值数量的时钟周期和/或以其它方式确定的)的代码区域。为了便于论述,取决于具体语境,在说明书通篇可互换使用术语“表达式”、“块”和/或“语句”。

应该认识到,重新排序变换可通过在代码区域内使用之前对一些阵列重新排序来影响代码区域。此外,可在代码区域之后使用的阵列可被反向重新排序(即,可施加重新排序的反向运算以将重新排序的阵列返回到其初始状态),以确保代码区域外部的程序代码不受影响。另外,如果代码区域包含流控制语句,则一个或多个阵列可沿代码区域中的各种路径排序和/或视情况而定反向重新排序以考虑到此类语句。在代码区域是线性循环区域的一些实施例中,重新排序可仅发生在代码区域外部。

图4a中示出了程序代码400的部分的示范实施例。如所示的,通用代码区域400包含由区域标识模块302识别的代码区域402以及所识别的代码区402外部的“print(x)”语句。应该认识到,代码区域402包含外部循环语句以及外部循环语句内的各种操作语句。如本文所描述的,在代码区域中使用的变量/阵列的一个或多个可被重新排序,其影响在程序代码400中呈现的语句/指令。例如,在一些实施例中,重新排序可涉及在代码区域402内插入“reorder()”语句和/或“reverse_reorder()”语句(如图4b所示的)(例如,除了将此类语句插入在代码区域402外部)以生成程序代码400的修改版本。在其它实施例中,重新排序可仅涉及将此类重新排序语句插入在代码区域402(例如线性循环区域)外部(如图4c中所示的)(例如紧接在代码区域402之前和之后)以生成程序代码400的修改版本。

分布性分析模块304配置成确定在所识别的代码区域中定义的表达式的一个或多个(例如每个)的分布性。也就是,分布性分析模块304可扫描代码区域中的所有表达式,并且确定重新排序是否在每个表达式上都是分布性的。在说明性实施例中,定义重新排序r可根据:如果x是矩阵(即相似性变换),则;如果x是向量,则;或者如果x是标量数字,则,其中p是置换矩阵,并且是p的转置/逆。另外,在说明性实施例中,如果其语义保持不变,则表达式上的重新排序r是分布性的(不管其输出是否被重新排序和/或其输入是否被重新排序)。换言之,,其中是输入的集合。

在一些实施例中,没有流控制语句的代码区域可被共同解释为单个表达式。如果重新排序在具体代码区域中的所有表达式上都是分布性的,则应该认识到,重新排序在作为说明性实施例中的共同表达式的整个区域上也是分布性的。像这样,为了对代码区域的结果重新排序,计算装置200可对到代码区域的输入重新排序,无需修改区域内部的代码。在代码区域的确包含流控制语句的实施例中,输入的一个或多个可能是有条件的,并且因此,那些输入的重新排序可能也是有条件的(例如参见图4b)。

应该认识到,一些常见的阵列相关表达式经常是分布性的。例如,表达式一般是分布性的,其中m和n是矩阵,v和w是向量,并且n是标量数字。此外,重新排序在没有输入和输出的表达式(例如条件“if(n)”和“goto”语句)上和在具有标量输入和输出的表达式上一般是分布性的。相比之下,一些其它常见的阵列相关的表达式不是分布性的。例如,要求输入和/或输出是具体“形状”(例如假定输入是上三角矩阵或下三角矩阵的三角求解器)的表达式、输入/输出表达式(例如打印命令)、要求逐位可再生性的表达式和/或对编译器314未知的函数一般可被视为非分布性的。应该认识到,如果用于具体用户定义的函数的源代码可用,则源代码可与本文描述的技术一致地进行分析以确定其分布性。尽管代码区域形成/标识和分布性分析在本文分开进行描述,但在一些实施例中,代码区域形成和分布性可同时进行分析。例如,在一些实施例中,计算装置200可开始于空区域,并且通过添加确认为分布性的语句来逐步“生长”区域。

活性分析模块306配置成确定在代码区域内一个或多个位置的一个或多个(例如每个)变量/阵列的活性(即,变量/阵列是活的还是死的)。例如,在一些实施例中,活性分析模块306可以确定在代码区域中的每个语句/表达式之前和/或之后的每个变量的活性。在说明性实施例中,变量/阵列被视为在程序代码中的具体编程点是活的,如果有可能该变量在将来(即在那个编程点之后)将被使用的话。应该认识到,计算装置200(例如编译器314)可利用用于确定变量活性的任何适合的技术、算法和/或机制。

相互依赖的阵列分析模块308配置成分析具体表达式以构造或者以其它方式确定表达式的相互依赖的阵列/变量的集群。在说明性实施例中,阵列的集合被视为彼此相互依赖的,如果那些阵列中的任何阵列的重新排序都会使其它阵列的重新排序成为必要的话。例如,如果表达式中的稀疏矩阵a被重新排序(例如一些列和/或行被交换),则向量x和y必须被重新排序。类似地,如果x或y重新排序,则a必须相应地重新排序。应该认识到,一般而言,向另一阵列指配涉及一个或多个阵列的表达式的语句指示那些阵列中每个阵列之间的相互依赖性。例如,如果代码区域包含语句,其中是阵列的表达式,则阵列是相互依赖的阵列。如下面所更详细描述的,在一些实施例中,相互依赖的阵列分析模块308可生成具体语句的表达式树,以便确定表达式的哪些变量/阵列是彼此相互依赖的,并由此生成集群。当然,在一些实施例中,语句可用3-地址格式(结果,算子和两个运算数)表达,其隐含地是表达式树,没有明确生成表达式树。

可重新排序阵列发现模块310配置成对所识别的代码区域执行双向数据流分析,以便发现代码区域中的可重新排序阵列。如下所述,在一些实施例中,可重新排序阵列发现模块310可基于后向传送函数(transferfunction)通过代码区域中的一个或多个表达式迭代地执行可重新排序阵列的后向传播,并基于前向传送函数执行前向传播。例如,在一些实施例中,可重新排序阵列发现模块310可识别具有数据局部性的可通过重新排序变换改进的稀疏阵列,并且通过双向流分析来分析/传播该阵列(例如以确定要重新排序的其它阵列)。在一些实施例中,此类阵列可以是与已知对代码区域重要的一些运算(例如稀疏矩阵向量乘法(spmv))相关的前一个或几个稀疏阵列。在另一实施例中,可重新排序阵列发现模块310可从用户接收要重新排序的第一阵列(far)(例如,经由代码区域的用户注释以便由编译器314分析)。

代码变换模块312配置成重新排序和/或反向重新排序代码区域中和/或程序代码中的代码区域周边(例如紧接在代码区域之前或之后)内的一个或多个阵列。在说明性实施例中,应该认识到,代码变换模块312确定要重新排序和/或反向排序的具体阵列以及在程序代码中的具体位置(在其处基于可重新排序阵列发现模块310的双向流分析执行此类操作)。另外,应该认识到,代码变换模块312可取决于具体实施例采用任何适合的重新排序算法,并且可利用任何适合的算法、技术和/或机制来实际实现程序代码的变换。

现在参考图5,在使用中,计算装置200可执行用于稀疏矩阵的自动重新排序的方法500(例如没有用户定向和/干预)。说明性方法500开始于框502,其中计算装置200接收包含可重新排序的一个或多个稀疏矩阵的程序(例如程序代码)。更确切地说,在一些实施例中,程序代码可由计算装置200的编译器314检索。在框504,计算装置200识别要分析的程序代码的代码区域以便重新排序阵列。如上所述,代码区域可以是程序代码的任何任意部分;然而,在一些实施例中,所识别/选择的代码区域是线性循环区域或程序代码的另一部分,在其处存在大量执行时间的。

在框506,计算装置200执行程序代码的代码区域的分布性分析以便确定在所识别的代码区域中定义的表达式的一个或多个(例如每个)的分布性。相应地,在框508,计算装置200可识别代码区域中的具体表达式,并且在框510,确定表达式上重新排序算法的分布性。例如,计算装置200可扫描代码区域中的所有表达式,并且确定重新排序是否在每一个表达式上都是分布性的。如上所述,在说明性实施例中,如果其语义保持不变,则表达式上的重新排序r是分布性的,不管其输出是否被重新排序和/或其输入是否被重新排序。也就是,如果,其中是输入的集合,则重新排序r在表达式上是分布性的。在一些实施例中,表达式可包含通常使用的已知是分布性的或非分布性的阵列相关表达式。相应地,在一些实施例中,计算装置200可确定在给定表达式中的具体阵列上执行的运算的类型。尽管分布性分析被描述为在代码标识之后,但在一些实施例中,分布性分析和代码标识可同时发生。例如,在一些实施例中,计算装置200可开始于空区域,并且通过添加识别为/已知是分布性的语句来逐步“生长”代码区域。

如果计算装置200在框512确定代码区域中的表达式的一个或多个是非分布性的,则方法500终止。然而,如果计算装置200确定重新排序在代码区域中的每一个表达式上都是分布性的,并且因此在总体代码区域上是分布性的,则在框514,计算装置200对代码区域执行活性分析以确定在代码区域内的各种编程点的阵列的一个或多个(例如每个)的活性。例如,在一些实施例中,计算装置200确定在代码区域中的每个语句/表达式之前和之后阵列是“活的”还是“死的”。如上面所指示的,计算装置200(例如编译器314)可采用用于确定变量活性的任何适合的技术、算法和/或机制。另外,尽管活性分析在图5中被显示为在分布性分析之后,但在一些实施例中,活性分析可在分布性分析之前执行。

在框516,计算装置200对代码区域中的一个或多个(例如每个)表达式执行相互依赖的阵列分析,以对于那些表达式中的每个,确定表达式的哪些阵列/变量是彼此相互依赖的,并基于该确定生成适当集群。换言之,计算装置200确定表达式阵列的重新排序是否会使表达式其它阵列的重新排序成为必要。例如,如上面所指示的,如果代码区域包含语句,其中是阵列的表达式,则阵列是相互依赖的阵列。在一些实施例中,计算装置200可执行方法600以生成并分析如图6中所示的表达式树,以便确定表达式的哪些变量/阵列彼此相互依赖,并由此生成集群。当然,在一些实施例中,语句可用3-地址格式(结果,算子和两个运算数)表达,其隐含地是表达式树,没有明确生成表达式树。

现在参考图6,说明性方法600开始于框602,其中计算装置200识别并选择代码区域的语句/表达式用于分析。作为示例,代码区域可包含由计算装置200选择的表达式,其中是向量,m是矩阵,并且是点积函数。在框604,计算装置200生成所选择的语句/表达式的表达式树。具体地说,计算装置200可生成表达式树700,如图7a所示的。如所示的,表达式树700包含多个内部节点和端节点。具体地说,在说明性实施例中,表达式树700包含指示运算(=、+、*和)的内部节点,并且包含指示对应运算的运算数的子节点。此外,表达式树700包含指示变量/阵列和/或标量常数(和m)的端节点。尽管示范表达式,并且因此表达式树700仅包含二进制运算,但应该认识到,任何具体表达式和表达式树在其它实施例中都可包含具有不同数量运算数的运算(例如由于表达式中的三元算子)。像这样,在其它实施例中,表达式树的具体操作节点可包含多于或少于2个的子节点。

在框606,如果可能的话,计算装置200将表达式树分成多个子树702。在这么做时,在框608,计算装置200可确定表达式树的内部节点的结果类型。在说明性实施例中,如果内部节点的结果类型是数字,则该节点与其父节点之间的边缘被打破,以将表达式树分成两个子树。如果内部节点是函数,则在一些实施例中,可分析函数的源代码以确定其结果类型。在其它实施例中,计算装置200可依靠函数的元数据(从计算装置200的用户接收的)来确定相互依赖的阵列分析的结果类型。在说明性实施例中,表达式树和/或子树被分解,直到原始表达式树不能被分成更小的子树。在涉及表达式树700的示范实施例中,运算生成标量值。相应地,通过打破节点与其父节点之间的链路将表达式树700分成2个子树702,如图7b中所示的。

在图6的框610,计算装置200生成或确定每个生成的表达式子树的相互依赖的阵列的集合/集群。具体地说,在说明性实施例中,具体子树中的每个阵列/变量都被包含在与该具体子树关联的结合/集群中。例如,在图7a-b的示范实施例中,第一子树702的阵列/变量被包含在第一集群中,而第二子树的阵列/变量被包含在第二集群中。在图6的框612中,计算装置200确定是否分析另一语句/表达式。例如,在说明性实施例中,计算装置200确定是否存在尚未对于表达式的阵列的相互依赖性进行分析的其它表达式。如果计算装置200确定分析另一表达式,则方法600返回到框602,其中计算装置200识别并选择另一表达式用于分析。

回头参考图5,在框518,计算装置200对所识别的代码区域执行双向数据流分析,以便发现代码区域中的可重新排序阵列。如下所描述的,应该认识到,计算装置200可利用前向和后向传播函数、前向和后向传送函数和/或其它函数,以便例如基于所提供的要重新排序的第一阵列(far)来发现可重新排序阵列。例如,可根据定义前向相互依赖的阵列传播函数,非空,其中是前向传播函数,b是表达式,x是要通过的输入阵列的集合,c是集群,并且c.rhs是集群的右手侧(即,指示由对应表达式使用的阵列)。此外,可根据定义后向相互依赖的阵列传播函数,非空,其中是后向传播函数,并且c.lhs是集群的左手侧(即,指示由对应表达式定义的阵列)。

例如,基于上面描述的示范表达式,相互依赖的阵列分析得出两个集群(例如基于两个子树702):第一集群和第二集群,其中|将定义的阵列/变量(即在左手侧的)与使用的阵列/变量(即在右手侧的)分开。

作为示例,在此类实施例中,应该认识到,,因为v1不包含在第一集群或第二集群的右手侧,,因为v2在第一集群的右手侧,,因为v2在第一集群的右手侧并且u不在集群的右手侧不影响结果,,因为v2在第一集群右手侧并且v4在第二集群的右手侧,,因为v1在第一集群的左手侧,并且,因为v1在第一集群的左手侧并且v4不在集群的左手侧不影响结果。

在说明性实施例中,可根据定义前向传送函数,其中是前向传播函数,b是表达式,x是要通过的可重新排序阵列的集合,是在语句b中定义的阵列的集合,并且是在语句b中使用的阵列的集合。应该认识到,前向传送函数指示从语句b前面到它后面按次序通过语句的右手侧和左手侧。应该进一步认识到,有两种情况可在通过具有前向传送函数的语句b传播期间发生,对于其可发生进一步“生长”:满足第一项的阵列和满足第二项的阵列。像这样,如果x中的输入阵列由语句b使用,则可重新排序阵列的新集合包含具有集群右手侧的阵列的所有集群。应该认识到,第一语句反映表达式右手侧的重新排序的阵列可使同一集群中的每个其它阵列的重新排序成为必要。另外,如果表达式b既不使用也不定义输入阵列,则该阵列也被包含在重新排序的阵列的新集合中。换言之,如果重新排序的输入阵列被通过,并且既不影响表达式b的任何阵列影响也不受其影响,则重新排序的输入阵列应该在表达式之后保持重新排序。

可根据定义后向传送函数,其中是前向传播函数,是后向传播函数,b是表达式,x是要通过的可重新排序阵列的集合,是在语句b中定义的阵列的集合,是在语句b中使用的阵列的集合,并且.rhs定义集群的右手侧。应该认识到,后向传送函数指示从语句b后面到它前面按次序通过语句的左手侧和右手侧。此外,应该进一步认识到,有三种情况可在通过具有后向传送函数的语句b传播期间发生,对于其可发生进一步“生长”:满足第一项的阵列、满足第二项的阵列或满足第三项的阵列。

在一些实施例中,计算装置200可执行方法800以执行双向数据流分析,如图8中所示的。在一些实施例中,双向数据流分析工作在控制流图(cfg)上,其中每个块b都是语句/表达式。说明性方法800开始于框802,其中计算装置200初始化代码区域中的语句/表达式的输入和输出集/状态。为了这么做,在代码区域外部的任何语句/表达式的输入和输出集可首先被初始化成空集。此外,在说明性实施例中,对于每个区域条目,输出集都被初始化成要重新排序的第一阵列(far)。如上面所指示的,far可由计算装置200的用户提供,或以其它方式由编译器314确定。对于代码区域中的其它语句,输出集可被初始化成全集。在一些实施例中,代码区域中的语句的输入集不初始化,因为他们可在随后的步骤中自动例示。更正式地说,在一些实施例中,代码区域外部的所有语句b都可根据初始化,其中是输入集,并且是输出集,并且代码区域内部的所有语句都可被初始化,使得如果b是条目,则,并且否则等于全集。

在框804,计算装置200预先调节代码区域中语句的输入和输出集。为了这么做,在框806,计算装置200可向语句应用前向传送函数。像这样,应该认识到,对于每个语句b,输入集都包含在其每个前任(predecessor)后面可重新排序的阵列,并且输出集是基于前向传送函数通过语句b传播的结果,其可被重复,直到输入集和输出集没有改变。更正式地说,在一些实施例中,可根据预先调节代码区域中(对于其b不是代码区域的条目)的所有语句b,其中pred()是b的前任表达式的集合。

在一些实施例中,在框808,计算装置200可选择传送函数优化(例如对于后向传送函数)。具体地说,在说明性实施例中,计算装置200可没有优化、具有基于阵列活性的优化或者具有基于代码区域中各种表达式的执行频率的优化,而应用后向传送函数。

在框810,计算装置200向代码区域中的语句应用后向传送函数。为了这么做,在框812,计算装置200可基于选择的优化应用后向传送函数。在说明性实施例中,后向传送函数可通过添加阵列(在其每个后继前面可重新排序)来扩大,和/或可通过添加基于具体后向传送函数通过b传播的结果的阵列来扩大。在采用活性优化的实施例中,如果在后继之前变量是“死”(即,在通过后继的任何执行路径中都不使用),则它可在后继前面人工重新排序,因为这么做不影响程序语义(例如,该阵列在那点无论如何都不使用)。在采用执行频率优化的实施例中,如果语句b具有多于一个后继块,并且执行频率显著不同(例如基于预先确定的阈值),则最频繁的后继x可以总是允许中的可重新排序阵列被传播到。例如,如果具体后继x在循环内,并且所有其它的都在循环外,则该后继x的传播可避免在语句b与x之间插入阵列的重新排序;当然,在一些实施例中,可能有必要在b与后继而不是x之间插入那些阵列中的一个或多个的反向重新排序函数。更正式地说,在一些实施例中,对于区域中的所有语句b,应用后向传送函数可根据:如果采用活性优化,则根据中的一个,如果采用执行频率优化,则根据,或者如果不采用优化,则根据,其中是语句b的所有后继的集合,,其中,并且在b的所有后继之间最频繁执行,是在后继s前面是死的但在其它后继前面不是死的(即,它们在所有后继之间是“部分死的”)的变量/阵列的集合,并且是在后继s前面是活的的变量/阵列的集合。

在框814,计算装置200向代码区域中的语句应用前向传送函数。应该认识到,对于前向传送函数的应用类似于上面相对于预先调节所描述的;然而,保持它们的原始值,并且随着新阵列“生长”。更正式地说,在一些实施例中,对于代码区域中的所有语句b都可根据应用前向传送函数。在框818,计算装置200确定无论输入和输出集都不改变。如果否,则方法800返回到框810,其中再次向语句应用后向传送函数。换言之,迭代地应用后向和前向传送函数,直到输入和输出集不改变并且稳定。

回头参考图5,在框520,计算装置200基于所发现的可重新排序阵列变换程序代码。具体地说,计算装置200配置成重新排序和/或反向重新排序代码区域中和/或程序代码中的代码区域周边(例如紧接在代码区域之前或之后)内的一个或多个阵列。如上面所指示的,计算装置200可利用任何适合的技术来实现程序代码本身的变换。在一些实施例中,对于代码区域中的任何语句b1,如果存在从语句b1到随后语句b2的边缘(例如在控制流图(cfg)中),其中b2例如是cfg中的另一块,则对于每个变量/阵列,如果但是,则程序代码“x=reorder(x)”可被插入在那个边缘,并且如果但是,则程序代码“x=reverse_reorder(x)”可被插入在那个边缘。在语句b2是代码区域的条目的实施例中,对于每个变量/阵列,如果,则程序代码“x=reorder(x)”可被插入在b2前面。

应该认识到,在一些实施例中,方法400、500、600和/或800中的任一个或多个可被实施为存储在计算机可读媒体上的各种指令,它们可由处理器210和/或计算装置200的其它组件执行以使计算装置200执行相应方法400、500、600和/或800。计算机可读媒体可被实施为能够由计算装置200读取的任何类型媒体,包含但不限于存储器214、数据存储装置216、计算装置200的其它存储器或数据存储装置、由计算装置200的外围装置220可读的便携式媒体和/或其它媒体。

部分表900描绘了来自向仅包含两个语句/块:的简单代码区域应用双向分析的结果。如所示的,在初始化阶段期间,b1的输出集被指配了要发现的第一阵列(far),其在此具体实施例中是(例如由用户选择的),并且b2的输出集被指配了全集。在预先调节期间,计算装置200如上所述应用前向传送函数的前向传递902,这导致b2被指配了的输出集。如所示的,语句b2的输入集与语句b1的输出集相同,因为在b1与b2之间没有改变该集合的语句。计算装置200随后应用后向传送函数的后向传递904,这导致b2具有的输入集,并且b1具有的输出集和的输入集。如所示的,在此类实施例中,计算装置200迭代地应用后向传送函数和前向传送函数,直到语句b1和b2中的每个的输入和输出集都不改变。

现在参考图10,示出了描绘来自程序代码的识别的代码区域的控制流图1000。如所示的,图100包含描绘程序代码的各种语句的多个块b1-b13。在说明性实施例中,所识别的代码区域包含块b1-b12,而块b13在代码区域外部。应该认识到,图11-16描绘了来自应用各种双向流分析算法(即具有和没有优化)的结果以及结果变换的程序代码。应该进一步认识到,尽管来自应用一种双向流分析算法(即具有优化)的结果变换代码可被视为来自另一双向流分析算法(例如没有优化)的结果变换代码中的提升/移动一些语句的后果,但用本文描述的技术可能没有必要这么做。在一些实施例中,可仅基于对应双向流分析算法的结果,生成每个结果变换的代码。

在图11中示出来自向图10的程序代码应用双向分析(没有优化)的结果的部分表1100。应该认识到,部分表1100(以及下面描述的表1300和1500)仅包含本文描述的初始化、预先调节和第一后向通过阶段。然而,实际上,可基于本文描述的技术完成整个表。如在与表1100对应的图12的控制流图1200中所示出的,变换程序代码以重新排序和反向重新排序在代码区域内各种编程点的变量/阵列(例如p、x、r和i)。

如上面所描述的,在一些实施例中,可优化双向流分析以考虑变量活性。在图13的表1300中部分示出了应用具有此类优化的双向流分析的结果,且在图14的控制流图1400中示出了对应变换的程序代码。如上面示出和描述的,与“部分死的”变量(例如a、p、r和i)关联的重新排序函数从代码区域内移动到代码区域之前以便更有效执行。在又其它实施例中,可优化双向流分析以考虑如上所述的执行频率。在图15的表1500中部分示出了应用具有此类优化的双向流分析的结果,而在图16的控制流图1600中描绘了对应变换的程序代码。如上面示出和描述的,在程序代码或者更确切地说代码区域(例如循环)的频繁执行区域内出现的重新排序函数可被移动到循环外部(例如在循环和/或代码区域前面)以改进执行。然而,在此类实施例中,可能有必要(例如在程序代码中存在条件语句的情形下)将附加反向重新排序函数放在代码区域内。例如,在说明性实施例中,在语句b2与b13之间包含反向重新排序函数,以确保到紧跟代码区域的“print(x)”语句的阵列/变量输出是准确的。

示例

下面提供了本文公开的技术的说明性示例。技术的实施例可包含下面描述的示例中的任一个或多个示例以及它们的任何组合。

示例1包含一种用于稀疏矩阵的自动重新排序的计算装置,所述计算装置包括:分布性分析模块,用于确定在程序代码的代码区域中定义的表达式的分布性,其中如果所述表达式的语义不受所述表达式的输入或输出的重新排序的影响,则所述表达式被确定成是分布性的;相互依赖的阵列分析模块,用于对所述表达式执行相互依赖的阵列分析以确定所述表达式的相互依赖的阵列的一个或多个集群,其中所述一个或多个集群的集群的每个阵列相互依赖于所述集群的每个其它阵列;以及可重新排序阵列发现模块,用于基于所述相互依赖的阵列的所述一个或多个集群借助于通过所述代码区域中的所述表达式的可重新排序阵列的迭代的后向传播和前向传播对所述代码区域执行双向数据流分析,其中所述后向传播基于后向传送函数,而所述前向传播基于前向传送函数。

示例2包含示例1的主题,并且进一步包含区域标识模块以识别所述程序代码的所述代码区域。

示例3包含示例1和示例2中任一示例的主题,并且其中识别所述代码区域包括识别包含循环体内的代码而不包含流控制语句的所述程序代码的线性循环区域。

示例4包含示例1-3中任一示例的主题,并且其中识别所述代码区域包括由所述计算装置的编译器识别所述代码区域。

示例5包含示例1-4中任一示例的主题,并且其中识别所述代码区域包括识别由所述计算装置至少在阈值时段内要执行的代码区域。

示例6包含示例1-5中任一示例的主题,并且其中所述区域标识模块进一步由所述计算装置的编译器接收所述程序代码。

示例7包含示例1-6中任一示例的主题,并且其中确定所述表达式的所述分布性包括确定在所述代码区域中定义的每个表达式的所述分布性。

示例8包含示例1-7中任一示例的主题,并且其中执行所述相互依赖的阵列分析包括响应于每个表达式是分布性的确定而执行所述相互依赖的阵列分析。

示例9包含示例1-8中任一示例的主题,并且其中确定所述表达式的所述分布性包括确定语句,其中是所述表达式;其中r是所述表达式上的重新排序;并且其中是输入的集合。

示例10包含示例1-9中任一示例的主题,并且其中确定所述表达式的所述分布性包括响应于确定如下至少一项而确定所述表达式是非分布性的:(i)所述表达式要求输入或输出结构具有特定形状;(ii)所述表达式定义所述程序代码的输入-输出函数;(iii)所述表达式要求逐位可再生性;或(iv)所述表达式包含对所述计算装置的编译器未知的函数。

示例11包含示例1-10中任一示例的主题,并且其中所述一个或多个集群的集群的每个阵列相互依赖于所述集群的每个其它阵列,使得所述一个或多个集群的具体集群中的一个阵列的重新排序影响所述具体集群的每个其它阵列。

示例12包含示例1-11中任一示例的主题,并且其中执行所述相互依赖的阵列分析包括:生成所述表达式的表达式树,其中所述表达式树的每个内部节点指示所述表达式的运算,而所述表达式树的每个端节点指示阵列或标量;基于所述阵列的相互依赖性将所述表达式树分成表达式子树的集合;以及基于包含在所述表达式子树中的所述阵列确定每个表达式子树的相互依赖的阵列的对应集群。

示例13包含示例1-12中任一示例的主题,并且其中将所述表达式树分成表达式子树的集合包括确定所述表达式树的每个内部节点的结果类型。

示例14包含示例1-13中任一示例的主题,并且其中执行所述双向数据流分析包括:初始化所述表达式的输入集和输出集;通过向要重新排序的第一阵列应用所述前向传送函数来预先调节所述表达式的所述输入集和所述输出集;以及迭代地应用所述后向传送函数和所述前向传送函数,直到所述输入集和所述输出集不改变。

示例15包含示例1-14中任一示例的主题,并且其中所述可重新排序阵列发现模块进一步从所述计算装置的用户接收所述要重新排序的第一阵列。

示例16包含示例1-15中任一示例的主题,并且其中迭代地应用所述后向传送函数和所述前向传送函数包括:迭代地应用所述后向传送函数和所述前向传送函数,直到每个表达式的输入集和输出集都不改变。

示例17包含示例1-16中任一示例的主题,并且进一步包含代码变换模块以基于所述双向数据流分析变换所述程序代码以重新排序至少一个阵列。

示例18包含示例1-17中任一示例的主题,并且进一步包含活性分析模块以确定在所述代码区域内的每个语句的所述代码区域中的每个变量的活性。

示例19包含一种稀疏矩阵的自动重新排序的方法,所述方法包括:由计算装置确定在程序代码的代码区域中定义的表达式的分布性,其中如果所述表达式的语义不受所述表达式的输入或输出的重新排序的影响,则所述表达式被确定成是分布性的;由所述计算装置对所述表达式执行相互依赖的阵列分析以确定所述表达式的相互依赖的阵列的一个或多个集群,其中所述一个或多个集群的集群的每个阵列相互依赖于所述集群的每个其它阵列;以及由所述计算装置基于所述相互依赖的阵列的所述一个或多个集群借助于通过所述代码区域中的所述表达式的可重新排序阵列的迭代的后向传播和前向传播对所述代码区域执行双向数据流分析,其中所述后向传播基于后向传送函数,而所述前向传播基于前向传送函数。

示例20包含示例19的主题,并且进一步包含:由计算装置识别程序代码的代码区域。

示例21包含示例19和20中任一示例的主题,并且其中识别所述代码区域包括识别包含循环体内的代码而不包含流控制语句的所述程序代码的线性循环区域。

示例22包含示例19-21中任一示例的主题,并且其中识别所述代码区域包括由所述计算装置的编译器识别所述代码区域。

示例23包含示例19-22中任一示例的主题,并且其中识别所述代码区域包括识别由所述计算装置至少在阈值时段内要执行的代码区域。

示例24包含示例19-23中任一示例的主题,并且进一步包含由计算装置的编译器接收程序代码。

示例25包含示例19-24中任一示例的主题,并且其中确定所述表达式的所述分布性包括确定在所述代码区域中定义的每个表达式的所述分布性。

示例26包含示例19-25中任一示例的主题,并且其中执行所述相互依赖的阵列分析包括响应于确定每个表达式是分布性而执行所述相互依赖的阵列分析。

示例27包含示例19-26中任一示例的主题,并且其中确定所述表达式的所述分布性包括确定语句,其中是所述表达式;其中r是所述表达式上的重新排序;并且其中是输入的集合。

示例28包含示例19-27中任一示例的主题,并且其中确定所述表达式的所述分布性包括响应于确定如下至少一项而确定所述表达式是非分布性的:(i)所述表达式要求输入或输出结构具有特定形状;(ii)所述表达式定义所述程序代码的输入-输出函数;(iii)所述表达式要求逐位可再生性;或(iv)所述表达式包含对所述计算装置的编译器未知的函数。

示例29包含示例19-28中任一示例的主题,并且其中所述一个或多个集群的集群的每个阵列相互依赖于所述集群的每个其它阵列,使得所述一个或多个集群的具体集群中的一个阵列的重新排序影响所述具体集群的每个其它阵列。

示例30包含示例19-29中任一示例的主题,并且其中执行所述相互依赖的阵列分析包括:生成所述表达式的表达式树,其中所述表达式树的每个内部节点指示所述表达式的运算,而所述表达式树的每个端节点指示阵列或标量;基于所述阵列的相互依赖性将所述表达式树分成表达式子树的集合;以及基于包含在所述表达式子树中的所述阵列确定每个表达式子树的相互依赖的阵列的对应集群。

示例31包含示例19-30中任一示例的主题,并且其中将所述表达式树分成表达式子树的集合包括确定所述表达式树的每个内部节点的结果类型。

示例32包含示例19-31中任一示例的主题,并且其中执行所述双向数据流分析包括:初始化所述表达式的输入集和输出集;通过向要重新排序的第一阵列应用所述前向传送函数来预先调节所述表达式的所述输入集和所述输出集;以及迭代地应用所述后向传送函数和所述前向传送函数,直到所述输入集和所述输出集不改变。

示例33包含示例19-32中任一示例的主题,并且进一步包含:由计算装置从计算装置的用户接收要重新排序的第一阵列。

示例34包含示例19-33中任一示例的主题,并且其中迭代地应用所述后向传送函数和所述前向传送函数包括:迭代地应用所述后向传送函数和所述前向传送函数,直到每个表达式的输入集和输出集都不改变。

示例35包含示例19-34中任一示例的主题,并且进一步包含:基于所述双向数据流分析变换所述程序代码以重新排序至少一个阵列。

示例36包含示例19-35中任一示例的主题,并且进一步包含:由计算装置确定在代码区域内的每个语句的代码区域中的每个变量的活性。

示例37包含计算装置,计算装置包括:处理器;以及存储器,所述存储器具有多个指令存储在其上,所述指令当由处理器执行时使计算装置执行示例19-36中任一示例的方法。

示例38包含一个或多个机器可读存储媒体,其包括多个指令存储在其上,所述指令响应于被执行而导致计算装置执行示例19-36中任一示例的方法。

示例39包含包括用于执行示例19-36中任一示例的方法的部件的计算装置。

示例40包含一种用于稀疏矩阵的自动重新排序的计算装置,所述计算装置包括:用于确定在程序代码的代码区域中定义的表达式的分布性的部件,其中如果所述表达式的语义不受所述表达式的输入或输出的重新排序的影响,则所述表达式被确定成是分布性的;用于对所述表达式执行相互依赖的阵列分析以确定所述表达式的相互依赖的阵列的一个或多个集群的部件,其中所述一个或多个集群的集群的每个阵列相互依赖于所述集群的每个其它阵列;以及用于基于所述相互依赖的阵列的所述一个或多个集群借助于通过所述代码区域中的所述表达式的可重新排序阵列的迭代的后向传播和前向传播对所述代码区域执行双向数据流分析的部件,其中所述后向传播基于后向传送函数,而所述前向传播基于前向传送函数。

示例41包含示例40的主题,并且进一步包含:用于识别程序代码的代码区域的部件。

示例42包含示例40和41中任一示例的主题,并且其中用于识别所述代码区域的部件包括用于识别包含循环体内的代码而不包含流控制语句的所述程序代码的线性循环区域的部件。

示例43包含示例40-42中任一示例的主题,并且其中用于识别所述代码区域的部件包括用于由所述计算装置的编译器识别所述代码区域的部件。

示例44包含示例40-43中任一示例的主题,并且其中用于识别所述代码区域的部件包括用于识别由所述计算装置至少在阈值时段内要执行的代码区域的部件。

示例45包含示例40-44中任一示例的主题,并且进一步包含:用于由计算装置的编译器接收程序代码的部件。

示例46包含示例40-45中任一示例的主题,并且其中用于确定所述表达式的所述分布性的部件包括用于确定在所述代码区域中定义的每个表达式的所述分布性的部件。

示例47包含示例40-46中任一示例的主题,并且其中用于执行所述相互依赖的阵列分析的部件包括用于响应于确定每个表达式是分布性的而执行所述相互依赖的阵列分析的部件。

示例48包含示例40-47中任一示例的主题,并且其中用于确定表达式的分布性的部件包括用于确定语句的部件,其中是所述表达式;其中r是所述表达式上的重新排序;并且其中是输入的集合。

示例49包含示例40-48中任一示例的主题,并且其中用于确定所述表达式的所述分布性的部件包括用于响应于确定如下至少一项而确定所述表达式是非分布性的部件:(i)所述表达式要求输入或输出结构具有特定形状;(ii)所述表达式定义所述程序代码的输入-输出函数;(iii)所述表达式要求逐位可再生性;或(iv)所述表达式包含对所述计算装置的编译器未知的函数。

示例50包含示例40-49中任一示例的主题,并且其中所述一个或多个集群的集群的每个阵列相互依赖于所述集群的每个其它阵列,使得所述一个或多个集群的具体集群中的一个阵列的重新排序影响所述具体集群的每个其它阵列。

示例51包含示例40-50中任一示例的主题,并且其中用于执行相互依赖的阵列分析的部件包括:用于生成所述表达式的表达式树的部件,其中所述表达式树的每个内部节点指示所述表达式的运算,而所述表达式树的每个端节点指示阵列或标量;用于基于所述阵列的相互依赖性将所述表达式树分成表达式子树的集合的部件;以及用于基于包含在所述表达式子树中的所述阵列确定每个表达式子树的相互依赖的阵列的对应集群的部件。

示例52包含示例40-51中任一示例的主题,并且其中用于将所述表达式树分成表达式子树的集合的部件包括用于确定所述表达式树的每个内部节点的结果类型的部件。

示例53包含示例40-52中任一示例的主题,并且其中用于执行所述双向数据流分析的部件包括:用于初始化所述表达式的输入集和输出集的部件;用于通过向要重新排序的第一阵列应用所述前向传送函数来预先调节所述表达式的所述输入集和所述输出集的部件;以及用于迭代地应用所述后向传送函数和所述前向传送函数直到所述输入集和所述输出集不改变的部件。

示例54包含示例40-53中任一示例的主题,并且进一步包含:用于从计算装置的用户接收要重新排序的第一阵列的部件。

示例55包含示例40-54中任一示例的主题,并且其中用于迭代地应用所述后向传送函数和所述前向传送函数的部件包括:用于迭代地应用所述后向传送函数和所述前向传送函数直到每个表达式的输入集和输出集都不改变的部件。

示例56包含示例40-55中任一示例的主题,并且进一步包含:用于基于所述双向数据流分析变换所述程序代码以重新排序至少一个阵列的部件。

示例57包含示例40-56中任一示例的主题,并且进一步包含:用于确定在代码区域内的每个语句的代码区域中的每个变量的活性的部件。

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