CSAPP【小白学习笔记】—— 第五章 优化程序性能

本文详细探讨了程序性能优化的策略,包括理解编译器优化的局限性,如内存别名使用和函数调用的影响。通过消除循环低效率、减少过程调用、消除不必要的内存引用等方式提升性能。现代处理器的指令级并行性是关键,通过循环展开、提高并行性和理解内存性能来优化。寄存器溢出和分支预测错误处罚是需要注意的限制因素。
摘要由CSDN通过智能技术生成

第五章 优化程序性能

  • 程序慢问题出现在哪里:

程序要实时地处理视频帧或者网络包

计算任务的计算量非常大

  • 编写高效的程序需要:

选择一组适当的算法和数据结构

编写出 编译器能够有效优化 以转换成高效可执行代码的源代码。(优化编译器的能力和局限性,例如指针运算和强制类型转换)

  • 程序优化步骤:

第一步 消除不必要的工作(不必要的函数调用、条件测试和内存引用)

第二步 利用处理器提供的 指令级并行 能力,同时执行多条指令。(并行)


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

  • 妨碍优化的因素
  1. 对程序使用 安全的优化内存别名使用

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

对于一个使用指针变量 p 和 q 的程序,考虑下列代码:

x = 1000; 
y = 3000;
*q = y;    /* 3000 */
*p = x;    /* 1000 */
t1 = *q;    /* 3000 or 1000 */

t1 的值最后取决于指针 p 和 q 是否指向内存中同一个位置。当 p 和 q 指向同一个位置时,反复被修改的是同一个单元的数据,先改成 y (3000)后改成 x (1000),最后指针 p 传给t1的值就是1000。
5.1

  1. 函数调用

考虑下列过程:

long f();

long func1(){
	return f() + f() + f() + f();
}

long func2(){
	return 4 * f();
}

似乎没有什么问题,那么
若有下列代码:

long counter = 0;

long f() {
	 return counter++;
}

这段代码修改了全局变量的一部分,导致func1的调用会返回 0+1+2+3 = 6 ,而func2的调用会返回4*0 = 0


5.2 表示程序性能

度量标准:每元素的周期数(Cycle Per Element, CPE)。
千兆赫兹(GHs)十亿周期每秒,例如,一个4GHs的时钟其周期为0.25纳秒,或250皮秒。用时钟周期来表示的是执行了多少条指令。


5.4 消除循环的低效率

代码移动(code motion):识别要执行多次(例如在循环里)但是计算结果不会改变的计算。


5.5 减少过程调用 (略)


5.6 消除不必要的内存引用

比如循环累乘,每次迭代用的是需要返回的那个值,那么每次迭代,累积变量的数值都要从内存读出再写入到内存。这样读写很浪费,每次迭代开始时从dest(累积变量)读出的值就是上次迭代最后写入的值。
对于这种情况引入一个临时变量acc,在循环中去迭代累乘,最后循环完成结果再存到dest里。

/*combine3*/
void combine3(vec_ptr v, data_t *dest)
 {
 	long i;
 	long length = vec_length(v);
	data_t *data = get_vec_start(v);

 	*dest = IDENT;
 	for (i = 0; i < length; i++) {
 		*dest = *dest OP data[i];
 	}
 }

conbine3,dest作为累乘变量。

/*combine4*/
void combine4(vec_ptr v, data_t *dest)
 {
 	long i;
	long length = vec_length(v);
 	data_t *data = get_vec_start(v);
 	data_t acc = IDENT;

 	for (i = 0; i < length; i++) {
 		acc = acc OP data[i];
 	}
 	*dest = acc;
 }

combine4,引入临时变量acc。
若OP为乘法,IDENT为常量1,设 v = [2, 3, 5]是一个有3个元素组成的向量,考虑下面两个函数调用:

combine3(v, get_vec_start(v) + 2);
combine4(v, get_vec_start(v) + 2);

这里get_vec_start(v)指向数组的首元。
两个函数执行结果如下:

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值