程序性能分析《一》

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

//程序优化示例

//待优化程序:

//定义一个抽象类型data_t,这里data_t可以被声明为int float double; typedef int data_t ;

typedef struct

{

int len;

data_t *data;

}vec_rec ,*vec_ptr;

#define IDENT 0

#define OPER +

#define IDENT 1

#define OPER *

//创建向量组

vec_rec new_vec(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;

}

//获取向量元素

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;

}

int vec_length(vec_ptr v)

{

return v->len;

}

//初始版本

void combine1(vec_ptr v,data_t * dest)

{

int i;

*dest=IDENT;

for(i=0;i

data_t val;

get_vec_element(v,i,&val);

*dest=*dest OPER val;

}

}

/*过程combine1调用vec_length(v)作为for循环的测试条件,影响了程序的性能对于整数加法的CPE(每元素周期数)为31.25,乘法的CPE为

33.25。所以我们对其进行优化。

*/

/*对于我们只是将vec_length过程移出循环,这个过程成为代码移动的优化

而这样的移动能将每个元素消除了10个时钟周期,加法的CPE变为20.66

乘法的 CPE变为21.25。这种移动在处理大型数据时尤为重要,会严重影响程序的性能。

*/

//改进版本1 消除循环低效率

void combine2(vec_ptr v,data_t * dest)

{

int i;

int length=vec_length(v);

*dest=IDENT;

for(i=0;i

data_t val;

get_vec_element(v,i,&val);

*dest=*dest OPER val;

}

}

/*从combine2 的代码中可以看出,每次循环都会调用get_vec_element

来获得一个元素,这个过程开销特别大,因为它要进行边界检查

所以我们对其进行优化,我们增加一个函数 get_vec_start

这个函数返回数组的起始地址.*/

data_t * get_vec_start(vec_ptr v)

{

return v->data;

}

//改进版 2 减少过程调用

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

*dest=*dest OPER data[i];

}

}

/*通过改进后的combine3的加法CPE降到6.00 ,乘法降到9.0 达到了将近3.5倍的性能.*/

/*我们继续对combine3进行汇编分析)(假设为乘法):

%ecx指向data,%edx指向i,%edi指向dest

1: .L18:

2 mov1 (%edi),%eax //读取 *dest

3 imull (%ecx,%edx,4),%eax //*dest *data[i]

4 movl %eax,(%edi)

5 incl %edx

6 cmpl %esi,%edx

7 jl .L18

指令2读取存放在dest中的值,指令4写回这个位置。

这正是降低性能的原因,因为下一次迭代时指令2

读取的值会是刚刚写回得那个值。

所以在优化过程中引入一个临时变量x,它用在循环中存放

计算出来的值,只有在完成循环后才存放在*dest中。

*/

//改进版本3 减少存储器引用

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;

*dest=IDENT;

for(i=0;i

x=x OPER data[i];

}

*dest=x;

}

/*

改进后我们发现汇编代码为:

1 L.24:

相关文档
最新文档