体系结构总结及名词解释

体系结构问题:被优化的代码调度利用了现代计算机体系结构的一些特性。这样的机器常常允许以流水线方式执行代码,也就是多条指令在同一个时刻处于不同的执行阶段。有些机器还允许多条指令在同一个时刻开始执行。

•数据依赖:在调度运算指令时,我们必须知道这些指令对于每个内存位置和寄存器的影响。如果一条指令必须在另一指令对某个内存位置写人之后才读取该位置的值,那么这两条指令之间具有真依赖关系。如果有一个对同一位置的读指令之后的写指令,那么两条指令之间就出现反依赖关系;当有两个对同一位置的写指令时就会出现输出依赖。

数组数据依赖关系分析

并行化或局部性优化经常对原程序中执行的运算重新排序。和所有的优化一样,只有当对运算的重新排序不会改变程序输出时才可以对这些运算重新排序。一般来说,我们不可能深人理解一个程序到底做了什么,代码优化通常选用一个较简单的、保守的测试方法来决定在什么时候可以肯定程序的输出不会受到优化的影响:检查在原程序中和在修改后的程序中,对同一内存位置的各个运算被执行的顺序是否一样。在当前的研究中,我们关注的是数组访问,因此数组元 素就是需要考虑的内存位置。

如果两个访问(不管是读还是写)指向两个不同的位置,显然它们是相互独立的(可以被重 新排序)。另外,读运算不会改变内存的状态,因此各个读运算之间是独立的。如果两个访问指向同一个内存位置并且其中至少有一个写运算,那么就说这两个访问是数据 依赖的。为了保证修改后的程序和原程序做同样的事情,每一对有数据依赖关系的运算在原程 序中的执行顺序必须在新的程序中得到保持。

整数线性规划

对数据依赖关系的分析要求找出是否存在一些整数满足由等式和不等式组成的约束系统。其中的等式是从数组访问的矩阵向量表示中得到的;不等式是从循环界限中得到的。等式可以用不等式表示:等式z 可以用两个不等式:x≥y和y≥x表示。

因此,数据依赖关系问题可以被表示为寻找满足一组线性不等式的整数解,这个问题就是众所周知的整数线性规划(integer linear programming)。整数线性规划是一个NP完全问题。虽然没有已知的多项式复杂性的算法,但人们研发了多种启发式解法来解决涉及很多变量的线性规划问题。这些解法在很多情况下运行得是相当快的。遗憾的是,这样的标准启发式解法并不适合数据依赖关系分析。在数据依赖分析中,问题的难点在于如何解决很多小且简单的整数线性规划,而不是大型的复杂整数线性规划。

多指令发送处理器

我们也可以使用仿射循环转换来优化多指令发送计算机的性能。一个软件流水线化循环的性能受到两个因素的限制:先后关系约束中的环,以及对关键资源的使用。通过改变最内层循环的组成,我们可以改进这些限制。

首先,我们可以使用循环转换来创立最内层的可并行化循环,从而完全消除先后关系约束中的环。假设一个程序有两个循环,其中的外层循环是可并行化的,而内层循环不可并行化。我们可以交换这两个循环,使得内层循环变成可并行化的,从而创造出更多的指令级并行化机会。请注意,我们并不要求最内层循环的迭代之间一定是完全可并行化的。只要其依赖关系所确定的环短到可以充分利用硬件资源就足够了。

缓冲区溢出

为了防止缓冲区溢出,我们要么必须通过静态的方法证明每个数组写运算都处于边界之内,要么必须进行适当的动态数组边界检查。因为在C和C++程序中必须手工插入这些边界检查,程序员很容易忘记插人测试代码,或者插人错误的测试代码。人们已经开发了启发式工具来检查是否在调用一个strcpy之前至少进行了某些测试,虽然这些测试不一定是正确的。
当一个由用户提供的精心制作的数据被写到了预想的缓冲区之外并操纵程序的执行时,就发生了缓冲区溢出攻击(buffer overflow attack)。比如,一个C程序可能从用户那里读取一个字符 串h然后使用函数调用

一个指针和引用的模型

因为我们进行的是上下文无关的分析,所以只需要断定一个给定的变量u能够指向一个给定的堆对象h,不需要指出在程序中的什么地方u可能指向h,或者在什么样的上下文中u可以指向h请注意,变量可以通过它的全名来命名。在Java中,这个全名包括了模块、类、方法和方法中的块以及变量名本身。因此,我们可以区分标识符相同的多个变量。
假设我们的语言可以用下列方式来表示和操作引用:

1)某些程序变量的类型为“指向T的指针”或“指向r的引用”,其中T是一个类型。这些变量可以是静态的,也可能位于运行时刻栈中。我们简单地称它们为变量。

相关指针分析

上下文相关性可以大大提高过程间分析的精确性。我们讨论了两种过程间分析的方法,一种基于克隆的方法,另一种是基于摘要的方法。那么我们应该使用哪一个方法呢?

在计算指针指向信息的摘要时有几个难点。首先,这些摘要很大。每个方法的摘要必须包括这个函数和所有被调用者可能做出的所有更新所产生的影响。这些影响需要用输人参数来表示。也就是说,一个方法可能改变的指向集合包括:所有可通过静态变量及输人参数到达的所有数据的指向集合,以及由该方法及被调用方法所创建的全部对象的指向集合。虽然人们已经给 出了复杂的解决方案,但是现在还没有解决方法可以被应用到大型程序中。即使摘要可以通过自底向上的方式计算得到,但如何在一个典型的自顶向下处理过程中计算所有上下文环境下的指针指向集合是一个更大的问题。因为上下文环境的数量可能按照指数级增长。这样的信息对于一些全局性查询是必须的,比如在代码中找出指向某个特定对象的所有指针。

使用BDD的Datalog的实现

二分决策图(Binary Decision Diagram,BDD)是一个用图来表示布尔函数的方法。因为对n个 变量有22n个布尔函数,没有哪种表示方法能够很简洁地表示所有的布尔函数。但是,在实践中出现的布尔函数常常具有很多规律。因此,人们常常可以找到一个BDD来简洁地表示他们想要表示的布尔函数。

我们为了分析程序而开发了一些Datalog程序。事实表明,用这些Datalog程序描述的布尔函数也不例外,也可以使用BDD简洁地表示。BDD方法在实践中是相当成功的,虽然我们需要通过商业BDD操作程序包中的一些启发式规则或技术才可以找到用以表示程序信息的简洁的BDD。值得一提的是,它比使用传统数据库管理系统的方法具有更好的性能,因为传统数据库管理系统是为了在典型商业数据中出现的更加不规则的数据模式而设计的。

LR语法分析中的错误恢复

当LR语法分析器在查询语法分析动作表并发现一个报错条目时,它就检测到了一个语法错误。在查询GOTO表时不会发现语法错误。如果当前已扫描的输入部分不可能存在正确的后续符号串,LR语法分析器就会立刻报错。规范LR语法分析器不会做任何多余的归约动作,会立刻报告错误。SLR和LALR语法分析器可能会在报错之前执行几次归约动作,但是它们决不会把一个错误的输人符号移人到栈中。

在LR语法分析过程中,我们可以按照如下方式实现恐慌模式的错误恢复策略。我们从栈顶向下扫描,直到发现某个状态s,它有一个对应于某个非终结符号A的GOTO目标。然后我们丢弃零个或多个输人符号,直到发现一个可能合法地跟在A之后的符号a为止。之后语法分析器将GOTO(s, A)压人栈中,继续进行正常的语法分析。在实践中可能会选择多个这样的非终结符号A。通常这些非终结符号代表了主要的程序段,比如表达式、语句或块。比如,如果A是非终结符号stmt,a就可能是分号或者。其中,标记了一个语句序列的结束。

封装方法

方法(method)封装了类的行为,提供了类的对外表现。用于将封装的内部细节以公有方法提供对外接口,从而实现与外部的交互与响应。例如,从上面属性的分析我们可知,实际上对属性的读写就是通过方法来实现的。因此,对外交互的方法,通常实现为public。

当然不是所有的方法都被实现为public,否则类内部的实现岂不是全部暴露在外。必须对对外的行为与内部操作行为加以区分。因此,通常将在内部的操作全部以private方式来实现,而将需要与外部交互的方法 实现为public,这样既保证了对内部数据的隐藏与保护,又实现了类的对外交互。例如在ATM类中,对钱的计算、用户验证这些方法涉及银行的关键数据与安全数据的保护问题,必须以private方法来实现,以隐藏对用户不透明的操作,而只提供返回钱款这一public方法接口即可。在封装原则中,有效地保护内部数据和有效地暴露外部行为一样关键。

«383940414243444546474849505152»
最近发表
控制面板
您好,欢迎到访网站!
  [查看权限]
网站分类
搜索
Tags列表
网站收藏
图标汇集
  • 订阅本站的 RSS 2.0 新闻聚合
友情链接

热门搜索: 外链域名 高外链域名 高收录域名

Copyright www.thyst.cn. Some Rights Reserved.