Chinaunix首页 | 论坛 | 博客
  • 博客访问: 72008
  • 博文数量: 14
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 76
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-03 08:59
文章分类

全部博文(14)

文章存档

2014年(13)

2013年(1)

我的朋友

分类: C/C++

2014-08-21 20:01:45

1、存储器别名
     这个时候需要考虑程序转化的安全难度:
    典型的案例是如下代码:
     void  twiddle1(int *xp,int *yp)
     {
        *xp+=*yp;
        *xp+=*yp;
       }
     void  twiddle2(int *xp,int *yp)
      {
          *xp+=2* *yp;
      }
     以上的代码看上去一样,但是明显twiddle2是twiddle1的优化版本。因为twiddle1中一共执行了load *xp  2次、load  *yp两次、store  *xp2次,一共6次对存储器的引用。而twiddle2只需要一次load *xp  、一次load *yp、一次store *xp,一共3次对存储器的引用 。
    因此我们在编译的时候会觉得twiddle2比twiddle高效。
    但是如果我们考虑程序的安全性来看。考虑下xp 等于yp的情况。
    此时twiddle1会执行
      *xp+=*xp;
      *xp+=*xp;
    结果是*xp的值会增加4倍
    此时twiddle2会执行
      *xp+=2* *xp;
    结果是*XP的值增加3倍。由此可见不能产生twiddle2作为twiddle1的优化版本。
  这种情况称为存储器别名使用(memory aliasing)。即两个指针可能会指向存储器中的同一个位置。
  因此安全的优化中必须考虑不同的指针可能指向存储器的同一个位置。
   测试代码:
   #include
    #include
   void twiddle1(int *xp,int *yp)
  {
   *xp+=*yp;
   *xp+=*yp;
   }


void twiddle2(int *xp,int *yp)
{
   *xp+=2* *yp;
}




int main(int argc,char **argv[])
{
   int a=3,b=2;
   twiddle1(&a,&b);
   printf("twiddle1   xp!=yp  *xp=%d  *yp=%d\n",a,b);
   a=3,b=2;
   twiddle2(&a,&b);
   printf("twiddle2   xp!=yp  *xp=%d  *yp=%d\n",a,b);
   a=5,b=5;
   twiddle1(&a,&b);
   printf("twiddle1   xp!=yp   *xp=%d  *yp=%d\n",a,b);
   a=5,b=5;
   twiddle2(&a,&b);
  输出结果:
jie@ubuntu:~/zhang/datastruct$ gcc twiddle.c 
./jie@ubuntu:~/zhang/datastruct$ ./a.out 
twiddle1   xp!=yp  *xp=7  *yp=2
twiddle2   xp!=yp  *xp=7  *yp=2
twiddle1   xp!=yp   *xp=15  *yp=5
twiddle2   xp!=yp   *xp=15  *yp=5
twiddle1    xp=yp    *xp=20
twiddle2   xp=yp    *xp=15



  再比如一下案例:
   x=1000;  y=3000;
  *q=y;
  *p=x;
    t1=*q;
  t1的值取决于指针p和指针q是否指向存储器中同一个位置。
   测试代码:
#include
#include
void t1(int *q,int *p)
{
 int x=1000,y=3000;
  int t;
  *q=y;
  *p=x;
  t=*q;
  printf("t=%d\n",t);
}
int main(int argc,char **argv[])
{
  int a=5,b=3;
  t1(&a,&b);
  t1(&a,&a);
}
输出结果:
 
jie@ubuntu:~/zhang/datastruct$ vi t1_t1.c 
jie@ubuntu:~/zhang/datastruct$ ./a.out 
t=3000
t=1000
第一次为3000 第二次为1000。原因就是存储器别名。两个指针指向同一个位置。




2、妨碍性能优化的因素是函数调用
      比如:
      f();
      int func1()
      {
        return f()+f()+f()+f();
       }
      int func2()
      {
        return 4*f();
       }
     看上去结果相同,但是考虑下f()的代码
     int f()
     {  
      return count++;
     }
   count作为全局变量。 func1的返回值将会是
  0+1+2+3=6
  func2的返回值是4*0=0;



   












阅读(1965) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~