讲述几点对程序进行效率优化的方法

本文通过具体示例探讨了程序优化的方法,包括消除循环低效、减少过程调用和消除不必要的存储器引用等,展示了如何通过这些手段显著提升程序性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前言

前几天看了深入理解计算机系统的 程序优化。因为前边两章节涉及到了太多的汇编,而本人不是计算机科班出身,计算机基础薄弱,看那些汇编代码的确很吃力, 打算以后对汇编慢慢来学习吧。毕竟学习不是一日之功。
看到程序优化这章节,感触颇深啊,平常一些编程细节没有注意,其实都是影响到程序整体性能的因素,通过分析程序底层细节,如何调用等才知道如何影响到了程序。好了,下面根据书中讲解,我来做一些简要的总结。给自己学习到的东西做一下记录吧。
2. 程序示例
本节主要讲述我们的系统是如何将我们的代码转换成更有效的代码,其实我们所做的程序,系统都在为我们默默的做程序优化。上一段代码
/* $begin adt */ /* Create abstract data type for vector */ typedef struct { long int len;//data数组的长度 data_t *data;//定义一个数组 /* $end adt */ int allocated_len; /* NOTE: we don't use this field in the book */ /* $begin adt */ } vec_rec, *vec_ptr; /* $end adt */
data_t是 这样定义的,因为本书可能会分析道不同的数据类型对程序的影响。 tydef int data _t;可能考虑到使用合并的一些运算特别定义了:
#define INDNT 0 #define OP + 他对向量求和使用声明: #define IDENT 1 #define OP * #include <stdlib.h> #include "combine.h" /* $begin vec */ /* Create vector of specified length */ vec_ptr new_vec(int len) { /* allocate header structure */ vec_ptr result = (vec_ptr) malloc(sizeof(vec_rec)); if (!result) return NULL; /* Couldn't allocate storage */ result->len = len; /* $end vec */ /* We don't show this in the book */ result->allocated_len = len; /* $begin vec */ /* Allocate array */ if (len > 0) { data_t *data = (data_t *)calloc(len, sizeof(data_t)); if (!data) { free((void *) result); return NULL; /* Couldn't allocate storage */ } result->data = data; } else result->data = NULL; return result; } /* * Retrieve vector element and store at dest. * Return 0 (out of bounds) or 1 (successful) */ int get_vec_element(vec_ptr v, int index, data_t *dest) { if (index < 0 || index >= v->len) return 0; *dest = v->data[index]; return 1; } /* Return length of vector */ int vec_length(vec_ptr v) { return v->len; } /* $end vec */ /* $begin get_vec_start */ data_t *get_vec_start(vec_ptr v) { return v->data; } /* $end get_vec_start */ /* * Set vector element. * Return 0 (out of bounds) or 1 (successful) */ int set_vec_element(vec_ptr v, int index, data_t val) { if (index < 0 || index >= v->len) return 0; v->data[index] = val; return 1; } /* Set vector length. If >= allocated length, will reallocate */ void set_vec_length(vec_ptr v, int newlen) { if (newlen > v->allocated_len) { free(v->data); v->data = calloc(newlen, sizeof(data_t)); v->allocated_len = newlen; } v->len = newlen; } 在 合并函数1中 #include "combine.h" /* Combining functions */ char combine1_descr[] = "combine1: Maximum use of data abstraction"; /* $begin combine1 */ /* Implementation with maximum use of data abstraction */ void combine1(vec_ptr v, data_t *dest) { int i; *dest = IDENT; for (i = 0; i < vec_length(v); i++) { data_t val; get_vec_element(v, i, &val); /* $begin combineline */ *dest = *dest OPER val; /* $end combineline */ } } /* $end combine1 */
未经优化的程序一般都是效率比较低的程序。在unix中,可以利用 ‘-O1’ 命令进行简单的优化。
3.消除循环低效率
上边的代码中,我们可以发现,在寻混内部for (i = 0; i < vec_length(v); i++) 中,我们每次循环都会调用vec_length(v)方法,其实求
vec_length(v)对程序是一个比较繁琐的的过程,当函数每次调用计算长度的时候就会产生效率低的问题,那么我们就要进行如下改进
void combine2(vec_ptr v, data_t *dest) { int i; int length = vec_length(v); *dest = IDENT; for (i = 0; i < length; i++) { data_t val; get_vec_element(v, i, &val); *dest = *dest OPER val; } }
这个时候,我们将代码移出了循环内部,我们只进行了一次 int length = vec_length(v); 求值。在书中有效率的比较已经达到了很大级别的提升了性能。
下面再来一个例子,
void lower1(char *s) { int i; for (i = 0; i < strlen(s); i++) if (s[i] >= 'A' && s[i] <= 'Z') s[i] -= ('A' - 'a'); } /* Convert string to lower case: faster */ void lower2(char *s) { int i; int len = strlen(s); for (i = 0; i < len; i++) if (s[i] >= 'A' && s[i] <= 'Z') s[i] -= ('A' - 'a'); } /* Implementation of library function strlen */ /* Compute length of string */ size_t strlen(const char *s) { int length = 0; while (*s != '\0') { s++; length++; } return length; }
在测试中,当对于个长度为1048576的字符串来说lower2函数只要1.5毫秒,比lower1快乐了500000 多倍。这是一个多么惊人的数字,所以我们要好好分析一下程序。
5.减少过程调用
像我们看到那样,过程调用会带来相当大的开销,而且妨碍大多数的形式程序优化。,在combin2中,可以看出,每次混换忒带都会调用get_vec_elenment来获取下一个向量元素。对每个向量引用,这个函数把向量索引I与循环边界作比较,很明显会造成效率低下的。
那么在combine函数中,我们增加一个函数get_vec_start。这个函数返回数组的起始地址。
data_t* get_vec_start(vect_pt v) { return v->data; } char combine3_descr[] = "combine3: Array reference to vector data"; /* $begin combine3 */ /* Direct access to vector data */ void combine3(vec_ptr v, data_t *dest) { int i; int length = vec_length(v); data_t *data = get_vec_start(v); *dest = IDENT; for (i = 0; i < length; i++) { *dest = *dest OPER data[i]; } } /* $end combine3 */
通过测试,提高效率比较小,那是怎么回事呢?请看下边一节。
6.消除不必要的存储器引用
在这里主要通过汇编代码能看出,程序的不停存储拷贝要是影响到程序的效率。
消除了无用存储器的读写。
char combine4_descr[] = "combine4: Array reference, accumulate in temporary"; /* $begin combine4 */ /* Accumulate result in local variable */ void combine4(vec_ptr v, data_t *dest) { int i; int length = vec_length(v); data_t *data = get_vec_start(v); data_t x = IDENT; for (i = 0; i < length; i++) { x = x OPER data[i]; } *dest = x; } /* $end combine4 */
通过这个修改,可以看到程序又有了一大步的提升。以上的代码的重构让我对程序的细节调整感受颇深。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值