《高性能科学与工程计算》——2.2 优化常识

2.2 优化常识

简单的代码修改经常会带来性能的显著提升。下面的章节总结了避免性能缺陷的几个最重要的“优化常识”。这些方法看似微不足道,但许多科学应用程序在应用这些方法后,性能都有了显著提升。
2.2.1 少做工作
重新组织代码以减少代码工作量,在很多情况下可显著提升性能。最常见的例子是循环检测一组对象是否具有特定属性,任一对象具备该属性即可:

如果complex_func()函数没有其他作用,FLAG是唯一和循环外部通信的变量。这种情况下,FLAG值一经改变,就立即退出循环可明显减少计算工作量(取决于条件判断变为true的概率):

2.2.2 避免耗时运算
算法的实现通常采用“步步为营”的策略。首先不做性能方面(因为在进行性能优化时,往往存在更改数值运算的风险)的考虑,将公式直接翻译成代码。第二步使用“便宜”运算替代“昂贵”运算。三角函数和幂运算是“强”运算(“昂贵”运算)的典型代表。记住类似x*2.0的表达式是不会被编译器优化成xx的,而指数(对数)的运算性能是很低的。避免“昂贵”运算的优化方法称为强度消减(strength reduction)。除上述简单情况外,“强”运算有时会关联一组有限的固定参数。下面是一个非平衡自旋系统仿真代码的例子:

程序的最后两行代码包含在一个循环中,并占用该应用程序几乎全部的运行时间。整型变量用于存储自旋取向(向上或者向下,对应值为1或者-1),所以变量edelz的取值范围为{-6,…,+6}。在整个应用程序中,tanh()函数即便用硬件实现也是最耗时的操作(至少几十个时钟周期)。根据以上描述,可根据参数范围将该函数结果转存在一个数组中,循环内部完全消除对tanh()函数的调用。假设tt为定值,那么这个表格只需创建一次:

这个数组存储在访存性能非常高的L1 cache中。因此,相对于tanh()函数,该数组的查找时间可以忽略不计。由于该数组尺寸较小且被频繁调用,所以整个计算过程都会被存储在L1 cache中。
2.2.3 缩减工作集
程序代码在计算过程中或至少在整体运行时间中的内存使用量称为该代码的工作集。一般情况下,压缩工作集会提高cache命中率,对性能提升有正面影响。如何实现工作集压缩以及是否会带来性能提升,很大程度上取决于算法和它的实现。上例中,原始代码使用了4字节的整除存储自旋取向,工作集也因此远远大于所有处理器的L2 cache。如果改变数组定义,使用1字节的整数来存储自旋取向。工作集会因此减小将近4倍,从而接近cache大小。
然而,并不是所有处理器都能有效处理“小”数据类型。如果处理器采用较大的字长,单字节类型数据通过移位和标记操作抽取,那么使用单字节整型数据的程序会非常低效。另一方面,如果可以采用SIMD指令,那么采用简单数据类型的程序就会非常高效(具体见2.3.3节)。

时间: 2025-01-21 16:39:24

《高性能科学与工程计算》——2.2 优化常识的相关文章

《高性能科学与工程计算》——2.5 C++优化

2.5 C++优化 目前,有大量关于如何编写高效C++代码的文献[C92,C93, C94, C95].我们的目标不是取代它们.所以我们特意忽略了引用计数.写时复制.智能指针等关键技术.本节以循环代码为例,根据我们的经验指出C++编程中经常存在的性能错误和误解. C++编程存在着一个根深蒂固的假象:编译器应该能够识别高级C++程序包含的所有抽象和代码混淆.首先,C++是一门支持复杂管理的高级编程语言,且自身特征明显(如运算符重载.面向对象.自动构建/销毁等).然而,这些特征绝大多数都不适合编写高

《高性能科学与工程计算》——第3章 数据访存优化3.1 平衡分析与lightspeed评估

第3章 数据访存优化 在高性能计算中,访存是最重要的性能限制因素.如前所述,微处理器的理论峰值性能和访存带宽存在固有的"不平衡性".因为很多科学和工程应用程序由需要大量数据传输的基于循环的代码构成,所以相对较低的内存(甚至是硬盘)访存带宽,就会导致片上资源的低效利用和程序性能的降低.图3-1综合显示了现代并行计算机系统的数据通路构成,以及在不同层次上的带宽和延迟范围.执行计算任务的功能部件位于该层次结构的顶部.在这些不同层次的数据通路中,访存带宽最大有3-4个数量级的差异,访存延迟最高

《高性能科学与工程计算》——第2章 串行代码基本优化技术2.1 标量剖析

第2章 串行代码基本优化技术 在千核级并行计算机时代,有些观点认为编写高效串行代码在许多领域已经有些过时了.因为增加更多CPU以获得大规模并行能力要比投入大量精力优化串行代码简单得多.这似乎是一个合理的理论,5.3.8节的论述中也体现了对这种观点的支持.然而,本书认为程序在单处理器上的性能优化毫无疑问是最重要的,如果通过一些简单的优化方法就可以实现两倍加速比,那么用户会更倾向于使用较少的CPU.这样不仅可把宝贵的计算资源释放给其他用户或项目,而且还可以使投入大量资金购买的硬件获得更加有效的利用.

《高性能科学与工程计算》——3.5 算法分类和访存优化

3.5 算法分类和访存优化 在基于cache的处理器上,许多循环的优化潜力可以通过观察某些基本参数(像数据传输.算术运算和问题规模的伸缩性)很容易地估算出来.从而进一步确定优化的努力是否有意义.3.5.1 O(N)/O(N)如果算术运算量和数据传输量(加载/写入)与问题规模(或者"循环长度")N成比例,那么优化潜力是非常有限的.标量乘.向量加和稀疏矩阵向量乘都是这类问题的典型实例.当N取值较大时,其性能不可避免地受访存限制,并且使用编译器生成的代码就可以达到较高的性能.这是因为O(N)

《高性能科学与工程计算》——1.2 基于高速缓存的通用微处理器体系结构

1.2 基于高速缓存的通用微处理器体系结构 微处理器可能是人类发明的最复杂的机器.然而,就像前面章节中描述的那样,它们都基于存储程序数字计算机的概念.对于科学家而言,理解CPU所有内部工作细节是不可能的,也是不必要的,尽管把握其高级特性对于了解潜在的性能瓶颈是有帮助的.图1-2展示了现代基于高速缓存的通用微处理器的简图.对于一个运行的程序,真正执行计算的部分是仅占芯片一小部分的浮点型(FP)和整型(INT)计算单元.其他逻辑控制单元用来向计算单元提供操作数.一般将CPU寄存器区分为浮点数和整数两

《高性能科学与工程计算》——1.6 向量处理器

1.6 向量处理器 从Cray 1超级计算机开始,直到基于RISC的高度并行计算机出现之前,向量机一直占据着科学计算的主要领域.在写这本书时,只有两家公司还在制造和销售向量机.但因为对内存带宽和运行时间有高度需求,向量机还是有着一个充满商机的市场. 根据设计,对于合适的可向量化的代码,向量处理器相较于标准的微处理器可以达到一个较好的实际性能.这种设计遵循单指令多数据(SIMD)的范例,即一条简单的机器指令被自动地应用于很多类型相同的参数.许多现代的基于cache的微处理器以扩展SISD指令集的形

《高性能科学与工程计算》——第1章 当代处理器1.1 存储程序的计算机体系结构

第1章 当代处理器 在1975-1995年的"旧时代"的科学计算时期,先进的高性能系统是专门为HPC市场设计的,主要的厂商有Cray.CDC.NEC.Fujitsu和Thinking Machines等.在性能和价格方面,这些系统远远超越了标准的"商品"电脑.20世纪70年代初发明的单芯片通用微处理器,是20世纪80年代末唯一足够成熟.可以打入HPC市场的技术.直到20世纪90年代末,标准的工作站集群甚至基于PC的硬件至少在理论峰值性能上才具备相应的竞争力.如今,情

《高性能科学与工程计算》——2.4 编译器作用

2.4 编译器作用 通过利用编译器自动优化,高性能计算程序可以获得不同程度的性能改进.几乎每个现代编译器都可以在命令行上设置编译选项,以便对编译器优化目标程序进行细粒度控制.有些情况下可以简单地通过更换一个编译器来检查程序是否还存在性能提升空间.编译器需要进行复杂的工作以将高级代码编写成的源程序编译为机器代码,同时要顾及到处理器内部资源.本章和下一章讨论的一些优化方法可以在某些简单情况下被编译器实现,但是涉及复杂的情况时就无法用编译器自动完成优化工作.始终要注意的一点是编译器可能足够聪明但是又可

《高性能科学与工程计算》——3.2 存储顺序

3.2 存储顺序 多维数组.矩阵或者类矩阵结构(最重要),在科学计算中无处不在.数据访问是一个关键的问题:标准计算机所固有的一维.基于cache行的内存布局和任何多维数据结构间的映射必须与数据读取与存储的顺序相匹配,这样才能充分利用空间和时间局部性.一维数组的非连续访存会减少空间局部性,从而导致访存带宽利用率的低效(见习题3.1).当处理多维数组时,这些访存模式可以很自然地产生. https://yqfile.alicdn.com/deee056f0c677b77e33166ab7f05e046