循环通过两个不同长度的矢量时的优化

时间:2016-11-09 18:16:04

标签: c++ performance compilation compiler-optimization

#include <vector>
#include <iostream>
#include <cmath>
#include <iomanip>
#include <sys/time.h>

using namespace std;

int main()
{
    struct timeval timeStart,
                    timeEnd;

创建随机0和1的向量。我们将基准时间来总结它们。

    int n1 = 450000000;  // size of vector v1
    int n2 = 500000000;  // size of vector v2
    int i;
    vector<bool> v1(n1);
    vector<bool> v2(n2);

    for (i=0; i < n1 ; i++)
    {
    v1[i] = rand() % 2;
    }
    for (i=0; i < n2 ; i++)
    {
    v2[i] = rand() % 2;
    }

总结的第一种技术。使用两个完整(独立)循环对这些向量求和

    int sum1 = 0;
    int sum2 = 0;
    gettimeofday(&timeStart, NULL);
    for (i=0; i < n1 ; i++)
    {
      sum1 += v1[i];
    }
    for (i=0; i < n2 ; i++)
    {
      sum2 += v2[i];
    }
    gettimeofday(&timeEnd, NULL);
    cout << "Two complete loops took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us"  << endl;

第二种技术。使用完整循环和部分循环对这些向量求和

    sum1 = 0;
    sum2 = 0;
    gettimeofday(&timeStart, NULL);
    for (i=0; i < n1 ; i++)
    {
      sum1 += v1[i];
      sum2 += v2[i];
    }
    for (i=n1; i < n2 ; i++)
    {
      sum2 += v2[i];
    }
    gettimeofday(&timeEnd, NULL);
    cout << "With a reduced second loop, it took " << ((timeEnd.tv_sec - timeStart.tv_sec) * 1000000 + timeEnd.tv_usec - timeStart.tv_usec) << " us"  << endl;

return 0;
}

我系统地获得了那种

的输出
Two complete loops took 13291126 us
With a reduced second loop, it took 12758827 us

我本来期望的是同一时间(如果编译器优化了第一个解决方案,因为我除外)或者我预计完整的两个循环需要花费相当多的时间(而不仅仅是5%-10%)部分第二循环。

编译器最有可能在这做什么?在循环通过两个不同长度的向量时,我是否应该考虑使用部分循环?

仅供参考,我用g++ -std=c++11 -o test test.cpp编译,版本为

g++ --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 7.0.2 (clang-700.1.81)
Target: x86_64-apple-darwin15.3.0
Thread model: posix

1 个答案:

答案 0 :(得分:1)

尝试解释执行时间的相似之处:

执行此操作时:

for (i=0; i < n1 ; i++)
{
  sum1 += v1[i];
}
for (i=0; i < n2 ; i++)
{
  sum2 += v2[i];
}

你执行2个循环以获得更多指令,但是你在两种情况下都读取连续内存:缓存以最佳方式工作(在“现代”计算机中花费大部分时间的内存访问/缓存未命中比执行代码更多)

BTW我怀疑编译器可以对这两个循环进行分组。

第二种情况需要较少的控制指令计数,但内存不会连续读取。

另外:优化器用于“展开”循环,从而减少控制指令的负面影响。

所以你在一方获得的,你在另一方面输了。这些优化需要加以改进,根据处理器架构的不同,您可能会有更大的变化。