博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
代码优化的一个小例子
阅读量:6039 次
发布时间:2019-06-20

本文共 2313 字,大约阅读时间需要 7 分钟。

考察以下代码:

#define IDENT 0#define OP *typedef int data_t;typedef struct{    long int len;    data_t *data;}vec_rec, *vecptr;vec_ptr NewVec(long int len){    vec_ptr result = (vec_ptr) malloc(sizeof(vec_rec));    if(!result){        return NULL;    }    result-> len = len;    if(len > 0){        data_t *data = (data_t*)calloc(len, sizeof(data_t));        if(!data){            free((void*) result);            return NULL;        }        result->data = data;    }    else{        result->data = NULL;    }    return result;}//Retrieve vector elemernt and store at destint GetVecElement(vec_ptr v, long int index, data_t *dest){    if(index < 0 || index >= v->len){        return 0;    }    *dest = v->data[index];    return 1;}long int VecLength(vec_ptr v){    return v->len;}void Combine1(vec_ptr v, data_t *dest){    *dest = IDENT;    for(long int i = 0; i < VecLength(v); ++i){        data_t val;        GetVecElement(v, i, &val);        *dest = *dest OP val;    }}

其中对于 Combine1(), 每次在 for 循环中进行检查时, 都要调用 VecLength() 获取链表长度, 可是在此例中链表的长度是不变的, 因此在首次获取链表长度之后, 接下来对 VecLength() 就成了累赘, 优化的方法就是消除循环的低效率:

//消除循环低效率后的代码void Combine2(vec_ptr v, data_t *dest){    long int length = VecLength(v);    *dest           = IDENT;    for(long int i = 0; i < length; ++i){        data_t val;        GetVecElemet(v, i, &val);        *dest = *dest OP val;    }}

对于 Combine2(), 每次循环迭代都会调用 GetVecElement() 来获取下一个向量元素, 对每一个向量引用都要把索引做边界检查明显会造成低效率, 所以就需要增加一个函数 GetVecStart() 这个函数来返回数组的起始地址, 从而直接访问数组以避免调用函数来获取每个元素.

//减少过程调用后的代码data_t* GetVecStart(vec_ptr v){    return v->data;}void Combine3(vec_ptr v, deta_t *dest){    long int length = vec_length(v);    data_t   *data  = GetVecStart(v);    *dest           = IDENT;    for(long int i = 0; i < length; ++i){        *dest = *dest OP data[i];    }}

在 Combine3 的 i 次迭代中, 程序需要读出指针 dest 所存放的寄存器的位置的值, 并乘以 deta[i], 再将结果存回 dest. 这样做很浪费, 因为每次迭代开始时从 dest 读出的值就是上次迭代最后写入的值. 解决方法就是引入一个临时变量存放在寄存器中来累计计算出来的值, 只有在循环完成之后才存放进 dest 中, 于是我们就把每次迭代的储存器操作从两次读和一次写减少到只需要一次读.

//消除不必要的储存器引用后的代码void Conbine4(vec_ptr v, data_t *dest){    long int length = VecLength(v);    data_t   *data  = GetVecStart(v);    data     acc    = IDENT;        //use local variable    for(long int i = 0; i < length; ++i){        acc = acc OP data[i];    }    *dest = acc;}

 

转载于:https://www.cnblogs.com/wuOverflow/p/4126065.html

你可能感兴趣的文章
kali 下 apache 配置文件
查看>>
C#中抽象类和接口的区别
查看>>
Android数据展示之ListView
查看>>
[詹兴致矩阵论习题参考解答]习题3.10
查看>>
真正的幽默,冯巩的55句经典语
查看>>
3.羽翼sqlmap学习笔记之Cookie注入
查看>>
一款基于jQuery可放大预览的图片滑块插件
查看>>
uCGUI窗口初始化过程
查看>>
junit参数化测试的使用方法
查看>>
redis笔记
查看>>
Nginx + CGI/FastCGI + C/Cpp
查看>>
java程序:set改造成map
查看>>
C++ 排序函数 sort(),qsort()的使用方法
查看>>
OC语言Block和协议
查看>>
使用xpath时出现noDefClass的错误(找不到某个类)
查看>>
OutputCache祥解
查看>>
【推荐】最新国外免费空间网站Hostinger
查看>>
.Net规则引擎介绍 - REngine
查看>>
微信消息回复C#
查看>>
JVM学习03_new对象的内存图讲解,以及引出static方法(转)
查看>>