计算机系统课程 笔记总结 CSAPP第五章 优化程序性能(5.1-5.14)

2023-11-14

目录

5.1 优化编译器的能力和局限性

5.2 表示程序性能

5.3 程序示例 

5.4 消除循环的低效率

5.5 减少过程调用

5.6 消除不必要的内存引用

5.7 理解现代处理器

5.7.2 功能单元的性能

5.7.3 处理器操作的抽象模型

5.8 循环展开

 

5.9 提高并行性

5.9.2 重新结合变换

5.10 优化合并代码的结果小结

5.11 一些限制因素

5.11.1 寄存器溢出

5.11.2 分支预测和预测错误惩罚

5.11.2.1 不要过分关心可预测的分支

5.11.2.2 书写适合用条件传送实现的代码

5.12 理解存储性能 

5.12.1 加载的性能

5.12.2 存储的性能

5.13 应用:性能提高技术

5.14 确认和消除性能瓶颈

5.14.1 程序剖析

5.14.2 使用剖析程序来指导优化


 

5.1 优化编译器的能力和局限性

  • 更可靠(各种条件下的正确性、安全性)
  • 可移植
  • 更强大(功能)
  • 更方便(安装、使用、帮助/导航、可维护)
  • 更规范(格式符合编程规范、接口规范 )
  • 更易懂(能读明白、有注释、模块化—清晰简洁)
  • 更正确(本课程重点!各种条件下)
  • 更省(存储空间、运行空间)
  • 更美(UI 交互)
  • 更快(本课程重点!本章重点!)

 

对优化的控制:指定优化级别

  • -O1 (普通)
  • -O2 (被接受)
  • -O3

优化可能会使语言和编码风格变得混乱降低程序的可读性和模块性,程序易出错难以修改和扩展

 

  • 两个指针可能指向同一个内存位置的情况称为内存别名使用
  • 在只执行安全的优化中,编译器必须假设不同的指针可能指向内存中同一个位置

 

  • 内联函数替换
    • 将函数调用替换为函数体

5.2 表示程序性能

  • 每元素的周期数(CPE)
    • 表示程序性能
    • eg.
      • 图像的像素
      • 矩阵中的元素
  • 4GHz
    • 表示处理器时钟运行频率为每秒4×109个周期
  • 时钟周期
    • 度量值表示执行了多少条指令

 

计算前置和

 

第二个函数使用:循环展开

  • 每次迭代两个元素

 

 

  • 性能比较:
    • 斜率,表示每元素的周期数(CPE)的值

 


5.3 程序示例 


5.4 消除循环的低效率

  • 代码移动
    • 减少计算执行的频率
      • 如果它总是产生相同的结果
      • 将代码从循环中移出
      • eg. strlen() 移除循环

 

复杂运算简化

  • 用更简单的方法替换昂贵的操作
    • 移位、加,替代乘法/除法
      • 16*x        -->        x << 4
    • 实际效果依赖于机器
    • 取决于乘法或除法指令的成本
      • Intel Nehalem CPU整数乘需要3个CPU周期
  • 识别乘积的顺序(Recognize sequence of products)
    • 识别产品(编译生成对的机器程序)的顺序

 

共享公用子表达式

  • 重用表达式的一部分
  • GCC 使用 –O1 选项实现这个优化

5.5 减少过程调用

函数调用

  • 程序行为中严重依赖执行环境的方面,程序员要编写容易优化的代码,以帮助编译器。
  • 将字符串转换为小写的函数
  • 平方级别的性能

  • 提高性能
    • 把调用 strlen 移到循环外
    • 根据:从一次迭代到另一次迭代时结果不会变化
    • ——代码移动的形式
  • 为什么编译器不能将strlen从内层循环中移出呢?
    • 函数可能有副作用
      • 例如:每次被调用都改变全局变量/状态
    • 对于给定的参数,函数可能返回不同的值
      • 依赖于全局状态/变量的其他部分
      • 函数lower可能与 strlen 相互作用
    • Warning:
      • 编译器将函数调用视为黑盒
      • 在函数附近进行弱优化
    • 补救措施:
      • 使用 inline 内联函数
        • 用 –O1 时GCC这样做,但局限于单一文件之内
      • 程序员自己做代码移动

 


5.6 消除不必要的内存引用

数值需要从内存中读出,再写入,浪费内存引用时间

  • 内存别名使用
    • 两个不同的内存引用指向相同的位置
    • C很容易发生
      • 因为允许做地址运算
      • 直接访问存储结构
    • 编译器不知道函数什么时候被调用,会不会在别处修改了内存,特别是并行化后,改变顺序的优化等。
    • 编译器保守的方法是不断的读和写内存,即使这样效率不高
    • 养成引入局部变量的习惯
      • 在循环中累积——用寄存器别名替换
        • 用一个局部变量计算后再引用内存
      • 告诉编译器不要检查内存别名使用的方法

 

 

 

 

 

 

 

 

 

 

 

 

 


 

5.7 理解现代处理器

现代CPU设计——流水线

利用指令级并行

  • 需要理解现代处理器的设计
    • 硬件可以并行执行多个指令
  • 性能受数据依赖的限制
  • 简单的转换可以带来显著的性能改进
    • 编译器通常无法进行这些转换
    • 浮点运算缺乏结合性和可分配性

现代CPU设计——超标量

超标量处理器

定义:一个周期执行多条指令. 这些指令是从一个连续的指令流获取的,通常被动态调度的.

5.7.2 功能单元的性能

  • 延迟
    • 表示完成运算所需要的总时间
  • 发射时间
    • 表示两个连续的同类型的运算之间需要的最小的时钟周期数
  • 容量
    • 表示能够执行该运算的功能单元数量
  •  
  • 延迟界限>=吞吐量界限
  • 延迟界限
    • 按照严格顺序完成合并运算的函数所需要的最小CPE值
  • 吞吐量界限
    • CPE最小界限
  •  
  • 计算n个元素的乘积/和
    • 需要大约 L×n+K 个时钟周期
    • L:合并运算的延迟;K:调用函数和初始化以及终止循环的开销
    • 此时CPE=L

5.7.3 处理器操作的抽象模型

  • 关键路径 critical path
    • 指明执行该程序所需时间的一个基本下界

 


5.8 循环展开

 

 

 

 

 

 

  • 增加每次迭代计算的元素的数量
  • 减少循环迭代次数
  • 优化性能
    • 减少了不直接有助于程序结果的操作的数量
      • 例如:循环索引计算、条件分支
    • 减少整个计算中关键路径上的操作数量

 

 

 

 

 

 

 

 

 

  • 基础优化
    • 把函数vec_length移到循环外
    • 避免每个循环的边界检查
    • 用临时/局部变量累积结果

 

 

 

 

 

 

 


 

 

 

 

 

 

 

 

5.9 提高并行性

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 计算 (长度=8)
    •  ((((((((1 * d[0]) * d[1]) * d[2]) * d[3]) * d[4]) * d[5]) * d[6]) * d[7])
  • 顺序依赖性Sequential dependence
    • 性能: 由OP的延迟决定

 

 

 

 

 

 

 

 

5.9.2 重新结合变换

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


5.10 优化合并代码的结果小结

 


5.11 一些限制因素

5.11.1 寄存器溢出

 

  • 并行度p超过可用的寄存器数量
    • 编译器溢出
    • 将某些临时值存放到内存中,通常是在运行时堆栈上分配空间
  • “维护多个累计变量的优势”就很可能消失
  • x86-64有足够多的寄存器,大多数循环在出现寄存器溢出之前就将达到吞吐量限制

 

5.11.2 分支预测和预测错误惩罚

 

 

  • 当遇到条件分支时,无法确定继续取指的位置
    • 选择分支:将控制转移到分支目标
    • 不选择分支:继续下一个指令
  •  直到分支/整数单元的结果确定后才能解决

 

分支预测

  • 猜测会走哪个分支
  • 在预测的位置开始执行指令
    • 但不要真修改寄存器或内存数据

 

 

5.11.2.1 不要过分关心可预测的分支

5.11.2.2 书写适合用条件传送实现的代码


 

5.12 理解存储性能 

  • 加载:从内存读到寄存器
  • 存储:从寄存器写到内存

5.12.1 加载的性能

  • 一个包含加载操作的程序的性能既依赖于
    • 流水线的能力
    • 加载单元的延迟
  • 对于两个加载单元而言
    • 其每个时钟周期只能启动一条加载操作
    • CPE不可能小于0.50
  • 对于每个被计算的元素必须加载k个值的应用
    • CPE不可能小于 k/2

5.12.2 存储的性能

  • 每个时钟周期开始一条存储
  • 存储操作不影响寄存器
    • 存储操作不会产生数据相关

 

  • 存储单元
    • 包含一个存储缓冲区
      • 包含已经被发射到存储单元而又还没有完成的存储操作的地址和数据
      • “完成”包括更新数据高速缓存
      • 使得一系列存储操作不必等待每个操作都更新高速缓存就能够执行

 


5.13 应用:性能提高技术

  • 高级设计
    • 选择适当的算法和数据结构
  • 基本编码原则
    • 避免限制优化的因素
      • 消除连续的函数调用
        • 尽可能将计算移到循环外
        • 妥协程序的模块性
      • 消除不必要的内存引用
        • 引入临时变量来保存中间结果
        • 只用在最后的值计算出来时,才将结果存放到数组和全局变量
  • 低级优化
    • 结构化代码以利用硬件功能
      • 展开循环,降低开销
      • 使用累积变量和重新结合,提高指令级并行
      • 用功能性的风格重写条件操作,使得编译采用条件数据传送

 


5.14 确认和消除性能瓶颈

  • 代码剖析程序 code profiler
  • Amdahl定律

 

5.14.1 程序剖析

 

  • gcc -Og -pg xxx.c -o xxx
  • ./xxx file.txt
  • gprof xxx
    • 产生文件gmon.out
    • 列出执行各个函数花费的时间

 

5.14.2 使用剖析程序来指导优化

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

计算机系统课程 笔记总结 CSAPP第五章 优化程序性能(5.1-5.14) 的相关文章

  • 【定点数运算】定点的乘法和加法

    目录 定点的介绍 定点的优势 定点数的乘法和加法 乘法 加法 定点的介绍 在之前的博客中介绍了定点数和浮点数 想要了解的可以前往以下链接 定点和浮点 定点数与浮点数的解释 定点的优势 使用定点表示有什么优势 为什么不简单地将所有值规范化为整
  • 重做日志缓冲区优化

    2008 05 05skate 重做日志缓冲区优化 学习目标 监视和确定重做日志缓冲区的大小 1 重做日志缓冲区的内容 A 对于每个dml或ddl语句 oracle服务器进程都会用户内存空间的重做条目复制到重做日志缓冲区上 B 重做条目包含
  • C/C++中的移位运算符——由二进制转换程序引发的思考

    以前学习移位运算符的时候并没有太多关注它 而此次关于移位运算符的探究 主要源于写的一个二进制显示的程序 include
  • 【linux】常用shell指令 [不断补充中...]

    前言 shell是一种脚本语言 需要有编译器执行 即 应用程序 gt shell gt 操作系统 gt 硬件 bash是linux下默认的shell sh是unix下默认的shell 多命令执行 xx xx 前面执行成功才会执行后面的命令
  • 8086CPU只有16位寄存器,却可以访问20位的物理地址

    一 背景介绍 Intel 8086是一个由Intel于1978年所设计的16位微处理器芯片 是x86架构的鼻祖 它是以8080和8085的设计为基础 拥有类似的寄存器组 但是数据总线扩充为16位 总线界面单元 Bus Interface U
  • 快速排序之“采取“尾递归”和“三数取中”技术的快速排序”

    快速排序之 采取 尾递归 和 三数取中 技术的快速排序 下面针对快速排序进行一些优化 QUICKSORT算法包含两个对其自身的递归调用 即调用PARTITION后 左边的子数组和右边的子数组分别被递归排序 QUICKSORT中的第二次递归调
  • 遗传算法初探——以电力系统有功优化为例(二)

    上一篇 https blog csdn net m0 43401436 article details 106564397 我自己的代码都差点认不出来了 完整代码如下 安装matpower后可直接运行 注释写得比较清楚 结合上一篇应该能看明
  • warning: dereferencing type-punned pointer will break strict-aliasing rules(转)

    warning dereferencing type punned pointer will break strict aliasing rules 在 gcc 2 x 下编译没有任何 warning 信息的代码换到 gcc 3 x 版本下
  • webpack打包文件过大的优化,提取第三方库(vue,ali-oss)到cdn,externals配置

    问题产生原因 vue或用其他第三方库webpack打包导致某单文件js过大 优化形式 webpack的externals配置 从输出的 bundle 中排除依赖 可将第三方库放到html用cdn加载 类似 调试方式 可参考vue cli 脚
  • CSS 图片偏移技术以及坐标问题

    CSS中通过图片偏移技术可以实现将众多小图标放入一个图片中 网页加载时只需要加载一个图片即可实现得到众多小图标的功能 这是前端设计时候对图片的一种优化方式 图片偏移技术只是一个属性而已 即 background position 100px
  • Base64编码(汇编版,未做过多优化,性能自认为还可以)

    感谢 DelphiGuy 于 2010 10 08 17 27 37 给出的提醒 function GetSizeCoder3To4 InputCount Integer Integer inline begin Result InputC
  • CSAPP Lab5- MallocLab

    实验目标 本实验需要用c语言实现一个动态的存储分配器 也就是你自己版本的malloc free realloc函数 实验步骤 tar xvf malloclab handout tar解压文件 我们需要修改的唯一文件是mm c 包含如下几个
  • 标准粒子群算法(PSO)及其Matlab程序和常见改进算法

    一 粒子群算法概述 粒子群优化算法 PSO 是一种进化计算技术 evolutionary computation 1995 年由Eberhart 博士和kennedy 博士提出 源于对鸟群捕食的行为研究 该算法最初是受到飞鸟集群活动的规律性
  • 【科普】CRC校验(一)什么是CRC校验?

    目录 CRC 循环冗余校验 CRC 校验码的生成 CRC 的发送方与接收方 发送方 接收方 除法异或运算示意图 CRC 循环冗余校验 CRC Cyclic Redundancy Check 循环冗余检验 是一种用于检测数字数据错误的技术 作
  • CSAPP——2.2整数表示

    两种整数 1 非负数 unsigned 2 负数 0 正数 T 补码 B 二进制 U 无符号数 1 整数数据类型 unsigned char short int long int32 t int64 t 2 无符号数的编码 假设位向量 x
  • STP与RSTP区别

    STP 不能快速迁移 即使是在点对点链路或边缘端口 边缘端口指的是该端口直接与用户终端相连 而没有连接到其它设备或共享网段上 也必须等待2 倍的ForwardDelay 的时间延迟 端口才能迁移到转发状态 RSTP Rapid Spanni
  • 【Unity Optimize】使用对象池(Object Pooling)优化项目

    目录 1 对象池 Object Pooling 介绍 2 实现对象池脚本 3 使用对象池生成Cube 4 效果展示 5 Unity资源商店的对象池插件 1 对象池 Object Pooling 介绍 Unity中的对象池 Object Po
  • 程序的链接

    程序的链接是一个非常实际的问题 他建立在很实际的问题之上 不从程序员的角度去思考问题 则是从软件的角度去思考如何复用错综复杂的代码 因为 这个问题的本质是我们没有给底层的硬件一个完整的可按顺序执行的程序 我们在前几章虽然讨论了指令流的问题
  • 计算机的保护模式与实模式

    一 背景 80386开始 CPU有三种工作方式 实模式 保护模式和虚拟8086模式 只有在刚刚启动的时候是real mode 等到操作系统运行起来以后就切换到protected mode 实模式只能访问地址在1M以下的内存称为常规内存 我们
  • 多线程编程与性能优化

    引言 在上一篇的入门篇中 我们对Android线程的基础概念和多线程编程模型有了初步了解 本篇将深入探讨多线程编程技术和性能优化策略 以提升应用的效率和响应性 高级多线程编程技术 使用线程池管理线程 线程池是一组预先创建的线程 用于执行任务

随机推荐

  • 全链路自动化测试

    背景 从 SOA 架构到现在大行其道的微服务架构 系统越拆越小 整体架构的复杂度也是直线上升 我们一直老生常谈的微服务架构下的技术难点及解决方案也日渐成熟 包括典型的数据一致性 系统调用带来的一致性问题 还是跨节点跨机房复制带来的一致性问题
  • 区块链赋能供应链金融

    点击观看大咖分享 小微企业 融资难 的诸多痛点 供应链金融的起源或者说初衷 是为了解决产业链上大量的小微企业 融资难 的诸多痛点 对于小微企业 它们在经营 发展的过程中是存在很多问题和困难的 比如小微企业信用状况差 金融资产获取困难 信息非
  • Springboot2.X 集成 Sharding-JDBC3.X

    之前的项目中集成了springboot2 x dangdang sharding jdbc 1 5 4 1 pom依赖
  • Error running tomcat7 Address localhost:1099 is already in use 错误解决

    在IDEA上运行web项目时报错 Error running 项目名 Address localhost 1099 is already in useTOC 第一步 按照Windows R键 输入cmd命令运行 第二步 按下回车键后进入界面
  • Unity按钮/button样式切换(非代码)

    Unity按钮 button样式切换 非代码 演示 创建一个Button 修改其的transition属性为Sprite Swap Source Image为默认情况下的button图片样式 Highlighted Sprite为鼠标进入b
  • 【NodeJS】nodejs

    1 安装指定版本 6 14是具体的版本号 npm install npm 6 14 g 2 安装最新版本 npm install g npm
  • 菜鸟仓库

    菜鸟仓库是一个很大很神奇的地方 各种琳琅满目的商品整整齐齐地摆放在一排排货架上 通常一种品类的商品会放置在货架的某一个格子中 格子设有统一的编号 方便工人们挑选 有一天沐哲取菜鸟仓库参观 无意中发现第1个货架格子编码为1 第2 3个分别为1
  • 机器学习决策树模型MATLAB

    主函数 clc clear all 西瓜数据集 data 青绿 蜷缩 浊响 清晰 凹陷 硬滑 是 乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 是 乌黑 蜷缩 浊响 清晰 凹陷 硬滑 是 青绿 蜷缩 沉闷 清晰 凹陷 硬滑 是 浅白 蜷缩 浊响 清晰
  • JAVA (11) date

    一 Date类 定义 java util Date 表示日期和时间的类 类 Date 表示特定的瞬间 精确到毫秒 毫秒 千分之一秒 1000毫秒 1秒 该类的时间原点 1970年1月1日 00 00 00 1 构造 实例代码 Date类的空
  • python十角星_使用 Python 绘制《星战》词云

    作者介绍 Rafael Schultze Kraft 前神经科学家 数据挖掘及机器学习的狂热爱好者 Python 的狂热粉丝 使用 Python 绘制 星战 词云 当前我们在 Jupyter Notebook 中推进的是一个有趣的小项目 它
  • VUE React Angular

    React 的Hooks 都有哪些 在那些场景中使用 1 useState useState通过在函数组件里调用它来给组件添加一些内部state React会在重复渲染时保留这个state useState会返回一对值 当前状态和一个让你更
  • matlab财务建模,探讨MATLAB结合EXCEL在财务管理建模中的一个综合运用

    一 财务建模与其理论基础所谓财务建模 是用数学术语或者计算机语言建立起来的表达财务问题各种变量之间关系的学科 财务建模是一门理论性很强的学科 具有坚实的理论基础和理论依据 其理论基础包括数学 经济学 金融学 统计学 会计学 计算机程序设计等
  • SpringBoot和Mybatis配置多数据源连接多个数据库

    目前业界操作数据库的框架一般是 Mybatis 但在很多业务场景下 我们需要在一个工程里配置多个数据源来实现业务逻辑 在SpringBoot中也可以实现多数据源并配合Mybatis框架编写xml文件来执行SQL 在SpringBoot中 配
  • Windows下配置QGIS和Python

    1 Windows下配置QGIS和Python 具体详细步骤参见 https guides lib utexas edu gis python qgis scripting 1 C Program Files QGIS 3 16 apps
  • 【小沐学Unity3d】Unity插件之天气系统UniStorm

    文章目录 1 简介 1 1 描述 1 2 兼容性 1 3 价格 1 4 特点 1 5 示例 3 安装 3 1 新建Unity项目 3 2 安装插件UniStorm 3 3 介绍UniStorm工具栏 3 4 入门使用 4 脚本开发 4 1
  • dma和通道的区别_Java中IO和NIO的本质和区别

    简介 终于要写到java中最最让人激动的部分了IO和NIO IO的全称是input output 是java程序跟外部世界交流的桥梁 IO指的是java io包中的所有类 他们是从java1 0开始就存在的 NIO叫做new IO 是在ja
  • 讯连科技威力导演20中文版

    威力导演也叫做CyberLink PowerDirector 是一款非常专业实用的非线性视频编辑神器 这款软件体积小巧 功能强大 即使是初学者也能够轻松使用 拥有入门初学者和专业工作者所需要的各种功能 能够帮助初学者快速入门 让专业工作者处
  • docker 安装与配置

    一 环境准备 IP 主机名 操作系统版本 docker版本 192 168 168 128 master01 CentOS Linux release 7 9 2009 Core docker 20 10 15 tgz 二 安装 安装包获取
  • 【超全汇总】VS2019+Qt15插件、安装、组件说明/问题解答/Qt实战(缺失Qtgui,无法打开.ui文件)

    本文介绍如何在VS2019中使用Qt 一 Qt安装 1 1 安装组件及说明 1 2 安装QT visual Studio Tool拓展 1 3 重启 配置插件 1 4 Qt实战演练 问题汇总 缺失Qtgui 无法打开 ui文件 由于版本兼容
  • 计算机系统课程 笔记总结 CSAPP第五章 优化程序性能(5.1-5.14)

    GitHub计算机系统CSAPP课程资源 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理 2 1 2 2 计算机系统课程 笔记总结 CSAPP第二章 信息的表示和处理 2 3 2 4 计算机系统课程 笔记总结 CSAPP第三章