二维矢量优化

时间:2014-01-30 04:59:22

标签: c++ optimization vector

这只是一个紧凑的测试用例,但我有一个双向量,我想填充所有成对差异的方阵(2D向量)。使用-O3优化编译时,我的计算机上大约需要1.96秒(仅从嵌套的双循环计算)。

#include <vector>
using namespace std;

int main(){
  vector<double> a;
  vector<vector<double> > b;
  unsigned int i, j;
  unsigned int n;
  double d;

  n=10000; //In practice, this value is MUCH bigger
  a.resize(n);

  for (i=0; i< n; i++){
    a[i]=static_cast<double>(i);
  }

  b.resize(n);
  for (i=0; i< n; i++){
    b[i].resize(n);
    b[i][i]=0.0; //Zero diagonal
  }

  for (i=0; i< n; i++){
    for (j=i+1; j< n; j++){
      d=a[i]-a[j];

      //Commenting out the next two lines makes the code significantly faster
      b[i][j]=d; 
      b[j][i]=d;
    }
  }
  return 0;
}

但是,当我注释掉这两行时:

b[i][j]=d; 
b[j][i]=d;

程序在大约0.000003秒内完成(仅从嵌套的双循环计算)!我真的没想到这两条线是限速步骤。我已经盯着这段代码一段时间了,我没有想法。任何人都可以提供任何关于如何优化这段简单代码的建议,以便大大缩短时间吗?

1 个答案:

答案 0 :(得分:1)

当您注释掉这两行时,嵌套循环中剩下的所有内容都是继续计算d然后丢弃结果。由于这不会对程序的行为产生任何影响,编译器将优化嵌套循环。这就是该计划几乎立即完成的原因。

事实上,我通过使用g++ -O3编译代码两次来确认这一点,一次只使用嵌套循环中的d=a[i]-a[j]语句,并且一次完全删除嵌套循环。发出的代码完全相同。

尽管如此,您的代码目前比以前慢,因为它缺少缓存。当您在这样的嵌套循环中访问二维数组时,如果可能,应始终安排迭代在内存中连续进行。这意味着第二个索引应该是变化更快的索引。对b[j][i]的访问违反了此规则并错过了缓存。所以让我们改写。

在:

for (i=0; i< n; i++){
    for (j=i+1; j< n; j++){
        d=a[i]-a[j];
        b[i][j]=d; 
        b[j][i]=d;
    }
}

定时:

real    0m1.026s
user    0m0.824s
sys     0m0.196s

后:

for (i = 0; i < n; i++) {
    for (j = 0; j < i; j++) {
        b[i][j] = a[j] - a[i];
    }
    for (j = i+1; j < n; j++) {
        b[i][j] = a[i] - a[j];
    }
}

定时:

real    0m0.335s
user    0m0.164s
sys     0m0.164s