代码优化的一个小例子

考察以下代码:

#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 dest
int 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值