《深入理解计算机系统(CSAPP)》第5章 优化程序性能 - 学习笔记

news2024/9/28 11:20:17

写在前面的话:此系列文章为笔者学习CSAPP时的个人笔记,分享出来与大家学习交流,目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记,在复习回看时发现部分内容存在一些小问题,因时间紧张来不及再次整理总结,希望读者理解。


《深入理解计算机系统(CSAPP)》第3章 程序的机器级表示 - 学习笔记_友人帐_的博客-CSDN博客

《深入理解计算机系统(CSAPP)》第5章 优化程序性能 - 学习笔记_友人帐_的博客-CSDN博客

《深入理解计算机系统(CSAPP)》第6章 存储器层次结构 - 学习笔记_友人帐_的博客-CSDN博客

《深入理解计算机系统(CSAPP)》第7章 链接- 学习笔记_友人帐_的博客-CSDN博客

《深入理解计算机系统(CSAPP)》第8章 异常控制流 - 学习笔记_友人帐_的博客-CSDN博客

《深入理解计算机系统(CSAPP)》第9章虚拟内存 - 学习笔记_友人帐_的博客-CSDN博客


第五章 优化程序性能

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

(1)编译器能做的优化

优化选项:-Ox:g-基本优化;1~3 - 更高级优化。

  • 寄存器分配
  • 代码选择与排序(调度)
  • 消除死代码
  • 消除轻微的低效率问题

(2)优化的局限性

  • 要在基本约束下运行:不能引起程序功能的任何改变;不去优化畸形情况下的程序行为。

  • 只在单个文件中进行优化分析,不做文件间的代码优化分析,代价太大。

  • 大多数分析都是基于静态信息,难以预测运行时的输入。

  • 遇到问题时必须对程序只使用安全的优化,偏保守。

2. 妨碍编译器优化的因素

  • 内存别名:两个指针指向同一个内存位置;因此编译器必须假设不同的指针可能会指向内存中同一个位置。

  • 函数调用:不能确定函数调用是否有副作用;因此编译器会假设最糟的情况并保持所有的函数调用不变。

解决方法:

  • 对于内存别名:

    消除不必要的内存引用:可以增加局部变量,将运算中间值累积在寄存器中,在整个过程结束后写回目标内存。

  • 对于函数调用:

    用内联函数替换优化函数调用:将函数调用展开替换为函数体;

    减少过程调用:尽量少地调用函数。

3. 优化方法

(1)不依赖处理器

  • 代码移动:如果某段代码总是产生相同的结果,就将其从循环中移出,避免重复计算。

  • 复杂运算简化:用更简单的方法替换昂贵的操作,例如使用移位、加代替乘法、除法。

  • 共享公用子表达式:找到多个计算的公共部分,重用表达式的一部分。

  • 尽量减少循环边界的检查

  • 消除不必要的内存引用,用局部变量累积结果

  • 使用AVX2编程,使用向量指令计算

(2)实现指令级并行

  • 循环展开

通过增加每次迭代计算的元素的数量,减少循环的迭代次数。减少了不直接有助于程序结果的操作的数量,例如循环索引计算和条件分支。它提供了一些方法,可以进一步变化代码,减少整个计算中关键路径上的操作数量。

k × 1 k\times 1 k×1展开

limit = length - k + 1;
for (i = 0; i < limit; i += k)
{
	// 对元素i到i+k-1合并运算
}
for (; i < length; i++)
{
	// 以每次处理一个元素的方式处理最后0~k-1个元素
}
  • 提高并行性

利用更多的功能单元来执行,比单个完全流水线化的功能单元更快,打破延迟界限。

使用多个累积量:对于可结合和可交换的合并运算可以通过将一组合并运算分割成两个或更多的部分,并在最后合并结果来提高性能。

k × n k\times n k×n展开:k次循环展开,n路并行

limit = length - k + 1;

for (i = 0; i < limit; i += k)
{
	// 对元素i到i+k-1合并运算
	// 使用n个累积量
}

// 处理最后0~k-1个元素

// n个累积量运算结果合并

最好使用 k × k k\times k k×k展开,且对于延迟为 L L L,容量为 C C C的操作而言,循环展开因子 k ≥ C ⋅ L k\ge C·L kCL时达到最大吞吐量。

展开变换时,必须考虑实现的功能是否与原来相同。要考虑运算是否可交换、可结合,溢出情况下是否保证结果与原来相同等。(浮点加法和乘法不可结合,原因在于四舍五入和溢出)

同时k不能过大,否则会出现寄存器溢出的情况:k的个数超过了机器的寄存器个数,会将变量分配在栈上,运行速度反而会降低。(x86-64处理器有16个寄存器,并可以使用16个YMM寄存器来保存浮点数)

  • 重组(重新结合变换)

改变运算顺序,以减少计算中关键路径上操作的数量,更好地利用功能单元的流水线能力。下一个循环的部分操作可以早一些开始。

称为 k × n a k\times na k×na展开。

4. 现代CPU设计

(0)基本概念

程序性能度量标准:每元素的周期数 (Cycles Per Element, CPE)

功能单元的性能:

  • 延迟(latency):表示完成运算所需要的总时间;

  • 发射时间(issue time):表示两个连续的同类型的运算之间需要的最小时钟周期数;

  • 容量(capacity):表示能够执行该运算的功能单元的数量。

  • 最大吞吐量:发射时间的倒数。一个完全流水线化(发射时间为1)的功能单元有最大的吞吐量,每个时钟周期进行一个运算。具有多个功能单元可以进一步提高吞吐量。对一个容量为C,发射时间为I的操作来说,处理器可能获得的吞吐量为每时钟周期C/I个操作。(每个时钟周期可以完成的操作数)

CPE值的两个基本界限:

  • 延迟界限(latency bound):因为在下一条指令开始之前,这条指令必须结束。给出了任何必须按照严格顺序完成合并运算的函数所需要的最小CPE值。理解:严格按照顺序执行,即使用一个功能单元,执行该合并运算最低能达到的CPE。(即为一个功能单元的极限,但可以通过增加功能单元并行计算以使实际运算速度突破这个界限)
  • 吞吐量界限(throughput bound):刻画了处理器功能单元的原始计算能力。这个界限是程序性能的终极限制。理解:比如执行整数加法的最大吞吐量为2,即每个时钟周期最多可以执行2次整数加法运算,故由于最大吞吐量为2,吞吐量对于整个合并运算的CPE限制为1/2=0.5,即由于最大吞吐量为2,整数加法的CPE最低只能到达0.5。

(1)现代处理器特点

能够实现指令级并行,同时对多条指令求值。

  • 超标量(superscalar):是它可以在每个时钟周期执行多个操作。把计算分解为多个阶段,在阶段间传递部分计算。
    在这里插入图片描述

  • 乱序的(out-of-order):指令执行的顺序不一定与它们在机器级程序中的顺序一致。

(2)主要组成部分

  • 指令控制单元(Instruction Control Unit, ICU):负责从内存中读出指令序列,并根据这些指令序列生成一组针对程序数据的基本操作。
  • ICU 从指令高速缓存 (instruction cache) 中读取指令,指令高速缓存是一个特殊的高速存储器,它包含最近访问的指令。通常,ICU会在当前正在执行的指令很早之前取指,这样它才有足够的时间对指令译码,并把操作发送到EU。
  • 取指控制的块包括分支预测,以完成确定取哪些指令的任务。
  • 指令译码逻辑接收实际的程序指令,并将它们转换成一组微操作。
  • 退役单元 (retirement unit) 记录正在进行的处理,控制寄存器文件中所记录的那些寄存器的更新。令译码时,关于指令的信息被放置在一个先进先出的队列中。这个信息会一直保持在队列中,直到发生以下两个结果中的一个。①一旦一条指令的操作完成了,而且所有引起这条指令的分支点也都被确认为预测正确,那么这条指令就可以退役(retired)了,所有对程序寄存器的更新都可以被实际执行了。②如果引起该指令的某个分支点预测错误,这条指令会被清空(flushed),丢弃所有计算出来的结果。
  • **执行单元 (Execution Unit, EU):**接收来自取指单元的操作并执行。每个时钟周期会接收多个操作 这些操作会被分派到一组功能单元中,分别用来专门处理不同类型的操作。
  • 读写内存是由加载和存储单元实现的。
  • 加载和存储单元通过数据高速缓存(data cache) 来访问内存。数据高速缓存是一个高速存储器,存放着最近访问的数据值。
  • 使用投机执行技术对操作求值,但是最终结果不会存放在程序寄存器或数据内存中,直到处理器能确定应该实际执行这些指令。分支操作被送到EU,确定分支预测是否正确。如果预测错误,EU会丢弃分支点之后计算出来的结果,还会发信号给分支单元,说预测是错误的,并指出正确的分支目的。在这种情况中,分支单元开始在新的位置取指。
  • 标记为执行“算术运算”的单元通常是专门用来执行整数和浮点数操作的不同组合。
  • 为了加速一条指令到另一条指令的结果的传送,执行单元可以直接将结果发送给彼此。

在这里插入图片描述

(3)现代处理器的一些功能

  • 分支预测(branch prediction):处理器会猜测是否会选择分支,同时预测分支的目标地址。

一种方式:投机执行(speculative execution):处理器会开始取出位于它预测的分支会跳到的地方的指令,并对指令译码,甚至在它确定分支预测是否正确之前就开始执行这些操作。如果过后确定分支预测错误,会将状态重新设置到分支点的状态,并开始取出和执行另一个方向上的指令。

  • 寄存器重命名

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/587015.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中如何判断是否为闰年

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;Java经典程序设计 目录 ✨介绍 &#x1f353;引言&#xff1a;闰年的定义和在编程中的应用 &#x1f353;目的&#xff1a;介绍如何使用Java编写一个函数来判断年份是否为闰年 ✨闰年的条件 ✨提供数学原理和背景知识 &…

软考A计划-试题模拟含答案解析-卷十一

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

牛客网刷题学习SQL(三)

SQL23 统计每个学校各难度的用户平均刷题数 首先分析题目&#xff1a; 想要计算一些参加了答题的不同学校、不同难度的用户平均答题量 不同学校&#xff1a; group by 学校 不同难度&#xff1a; group by 难度 平均答题量&#xff1a;注意用户去重&#xff0c;还有指定questi…

python:绘制GAM非线性回归

作者&#xff1a;CSDN _养乐多_ 本文将介绍使用python语言绘制广义线性模型&#xff08;Generalized Additive Model&#xff0c;GAM&#xff09;非线性回归散点图和拟合曲线。并记录了计算RMSE、ubRMSE、R2、Bias的代码。 文章目录 一、GAM非线性回归详解二、代码三、计算RM…

华为OD机试真题B卷 Java 实现【统计字符】,附详细解题思路

一、题目描述 输入一行字符&#xff0c;分别统计出包含英文字母、空格、数字和其它字符的个数。 数据范围&#xff1a;输入的字符串长度满足 1 \le n \le 1000 \1≤n≤1000 。 二、输入描述 输入一行字符串&#xff0c;可以有空格。 三、输出描述 统计其中英文字符&#…

chatgpt赋能python:Python中如何空一行

Python中如何空一行 在Python编程中&#xff0c;许多情况下我们需要在输出内容的时候空出一行。今天我们将介绍如何在Python中实现空一行的方法。 方法1&#xff1a;使用print()函数 在Python中&#xff0c;我们可以使用print()函数打印空行。我们只需在print()函数中输入两…

并发编程 原子性 可见性 有序性

并发编程的三个重要特性 原子性所谓原子性是指在一次的操作或者多次操作中&#xff0c;要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断&#xff0c;要么所有的操作都不执行。可见性可见性是指&#xff0c;当一个线程对共享变量进行了修改&#xff0c;那么另…

chatgpt赋能python:Python中如何合并列表-详细教程

Python中如何合并列表 - 详细教程 在Python编程中&#xff0c;有时候需要把两个或多个列表合并成一个单一的列表&#xff0c;以便更好地进行数据处理。Python中有几种方法可以实现列表合并&#xff0c;本文将介绍其中的三种方法。 1. 使用“”符号 最常见的方法是使用“”符…

InsCode AI 创作助手:源于 CSDN 的 AI 创作助手,不一样的创作体验

文章目录 &#x1f4cb;前言&#x1f3af;AIGC 时代的产物&#x1f3af;InsCode AI 创作助手体验&#x1f3af;一些感受和建议&#x1f9e9;感受&#x1f9e9;建议&#xff08;个人看法&#xff09; &#x1f4dd;最后 &#x1f4cb;前言 是的没错&#xff0c;CSDN AI 写作助手…

Vue组件化开发

1. 认识组件 1.1 基础示例 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widt…

STM32CubeIDE + HAL + STM32f103C8T6 系列教程1 ---板载PC13LED闪烁

STM32CubeIDE HAL STM32f103C8T6 系列教程1 --- 板载PC13LED闪烁 引言硬件关于开发板[^2]控制器内置存储器原理图 硬件连线硬件连接表硬件连线图 软件STM32CubeIDE下载及安装Stm32CubeIDE设置补全快捷键和主题新建一个工程选择开发板核心芯片型号设置工程相关参数STM32CubeMX…

最热门高效的Node.JS开源第三方开发库和特点(持续更新......)

目录 1. Express 2. Socket.io 3. Mongoose 4. Passport 5. Async 6. PM2 7. Nodemailer 8. Request 9. Cheerio 10. Lodash 11. Bluebird 12. Winston 13. Socket.io-client 14. Node-sass 15. Moment 16. Gulp 17. Grunt 18. Chai 19. Sinon 20. Nodemon…

Java线程之间如何通信的,有哪些方式?

线程之间的通信方式主要有以下几种&#xff1a; 共享变量&#xff1a;线程之间可以通过共享变量来进行通信。不同的线程可以共享同一个变量&#xff0c;并在变量上进行读写操作。需要注意的是&#xff0c;共享变量可能会引发线程安全问题&#xff0c;需要通过同步机制来确保线程…

chatgpt赋能Python-python中怎么导入numpy

介绍 Python是一种广泛使用的编程语言&#xff0c;具有许多内建功能和模块&#xff0c;让开发者能够快速地编写代码。然而&#xff0c;虽然能够实现许多计算&#xff0c;但是原始Python本身并不足够处理各种科学和数字计算上需要的高效性&#xff0c;因此numpy这个开源的Pytho…

chatgpt赋能python:Python中如何对文本进行修改

Python中如何对文本进行修改 在Python编程中&#xff0c;涉及到文本操作的场合并不少见。我们可能需要读取文件、解析HTML网页、处理字符串等等。而在对文本进行操作的过程中&#xff0c;修改文本是非常常见的需求。本文将介绍Python中对文本进行修改的几种基本方法。 1. 字符…

实验篇(7.2) 04. 映射内网服务器到公网IP ❀ 远程访问

【简介】由于服务器的IP是内网地址&#xff0c;所以无法从公网直接访问服务器。要想远程访问服务器&#xff0c;最简单的办法就是将服务器映射到公网IP&#xff0c;然后通过公网IP加端口号的方式进行访问。 实验要求与环境 OldMei集团深圳总部部署了一台服务器&#xff0c;用来…

微服务实战项目-学成在线-内容管理模块(有项目实战实现)

内容管理模块 1 模块需求分析 1.1 什么是需求分析 在百度百科中对需求分析的定义如下&#xff1a; 需求分析也称为软件需求分析、系统需求分析或需求分析工程等&#xff0c;是开发人员经过深入细致的调研和分析&#xff0c;准确理解用户和项目的功能、性能、可靠性等具体要…

Golang每日一练(leetDay0081) 基本计算器I\II Basic Calculator

目录 224. 基本计算器 Basic Calculator &#x1f31f;&#x1f31f;&#x1f31f; 227. 基本计算器 II Basic Calculator &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专栏 Python每日一练 专栏 C/C…

OpenAI API最新速查表;轻松制作数字分身;8个ChatGPT「作弊」策略;微软提示工程官方教程 | ShowMeAI日报

&#x1f440;日报&周刊合集 | &#x1f3a1;生产力工具与行业应用大全 | &#x1f9e1; 点赞关注评论拜托啦&#xff01; &#x1f916; The OpenAI API in Python 最新速查表 ShowMeAI知识星球资源编码&#xff1a;R102 大语言模型的发展&#xff0c;正在推动 OpenAI API…

chatgpt赋能python:Python中的宏定义及其使用

Python中的宏定义及其使用 Python是一种高级编程语言&#xff0c;其灵活性和可读性深受程序员的喜爱。Python中的宏定义是一种强大且实用的编程特性&#xff0c;在编写复杂程序时可以提高程序的可重用性和可扩展性。 什么是宏&#xff1f; 在计算机编程中&#xff0c;宏是一…