消除不必要的内存引用

消除不必要的内存引用

Content #

在某些情况下,可能只需要对程序的结构稍作调整,便能在很大程度上提升程序的运行性能。你可以先看看下面这段代码,思考下优化方式:

#define LEN 1024
int data[LEN] = { ... };
int foo(int* dest) {
  *dest = 1;
  for (int i = 0; i < LEN; i++) {
    *dest = *dest * data[i];
  }
}

在这段代码中,函数 foo 主要用来计算数组 data 中所有元素的乘积,并将计算结果值拷贝给指针 dest 所指向的整型变量。函数的逻辑很简单,但当仔细观察函数 foo 内部循环逻辑的实现时,便会发现问题所在。

在这个循环中,为了保存乘积在每一次循环时产生的累积值,函数直接将这个值更新到了指针 dest 指向的变量中。并且,在每次循环开始时,程序还需要再从该变量中将临时值读取出来。知道,从内存中读取数据的速度是慢于寄存器的。因此,这里可以快速想到一个优化方案。优化后的代码如下所示:

#define LEN 3
int data[LEN] = { 1,2,4 };
int foo(int* dest) {
  register int acc = 1;
  for (int i = 0; i < LEN; i++) {
    acc = acc * data[i];
  }
  *dest = acc;
}

在上面的代码中,一共做了两件事情:

  1. 将循环中用于存放临时累积值的 “*dest” 替换为一个整型局部变量 “acc”;
  2. 在定义时为该变量添加额外的 register 关键字,以建议编译器将该值存放在寄存器中,而非栈内存中。

通过消除不必要的内存引用,就能够减少程序访问内存的次数,进而提升一定的性能。

Viewpoints #

From #

18|极致优化(上):如何实现高性能的 C 程序?