我正在测试std :: vector上不同方式循环的速度.在下面的代码中,我考虑了5种方法来计算N = 10000000个元素的向量的所有元素的总和:
代码用g ++ for windows编译,用于编译的命令行是:
g++ -std=c++11 -O3 loop.cpp -o loop.exe
Run Code Online (Sandbox Code Playgroud)
我运行代码4次,测量每种方法的时间,我得到以下结果(时间以微秒为单位,最大值和最小值给出):
这些实验似乎表明的是:
循环使用迭代器与整数索引没有太大区别,至少在完全优化时是这样.
展开循环可以获得回报
令人惊讶的是,stl :: accumulate的性能更差.
虽然结论1和2是预期的,但数字3却相当令人惊讶.难道不是所有书都说使用STL算法而不是自己编写循环吗?
我在衡量时间或者解释结果的方式上是否犯了任何错误?如果您尝试下面给出的代码,你们有不同的情况吗?
#include <iostream>
#include <chrono>
#include <vector>
#include <numeric>
using namespace std;
using namespace std::chrono;
int main()
{
const int N = 10000000;
vector<int> v(N);
for (int i = 0; i<N; ++i)
v[i] = i;
//looping with iterators
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
long long int sum = 0;
for (auto it = v.begin(); it != v.end(); ++it)
sum+=*it;
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
cout << duration << "microseconds output = " << sum << " (Iterators)\n";
}
//looping with integers
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
long long int sum = 0;
for (int i = 0; i<N; ++i)
sum+=v[i];
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
cout << duration << "microseconds output = " << sum << " (integer index)\n";
}
//looping with integers (UNROLL 2)
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
long long int sum = 0;
for (int i = 0; i<N; i+=2)
sum+=v[i]+v[i+1];
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
cout << duration << "microseconds output = " << sum << " (integer index, UNROLL 2)\n";
}
//looping with integers (UNROLL 4)
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
long long int sum = 0;
for (int i = 0; i<N; i+=4)
sum+=v[i]+v[i+1]+v[i+2]+v[i+3];
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
cout << duration << "microseconds output = " << sum << " (integer index, UNROLL 4)\n";
}
//using std::accumulate
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
long long int sum = accumulate(v.begin(), v.end(), static_cast<long long int>(0));
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::microseconds>( t2 - t1 ).count();
cout << duration << "microseconds output = " << sum << " (std::accumulate)\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用标准库算法的原因不是获得更好的效率,而是为了让你在更高的抽象层次上思考。
虽然在某些情况下该算法可能比您自己的手写代码更快,但这并不是它们的目的。C++ 的一大优点是,当您有特定需求时,它允许您绕过内置库。如果您的基准测试显示标准库导致严重的速度下降,您可以自由地探索经典的替代方案,例如循环展开。对于大多数目的来说,这永远是不必要的。
话虽如此,一个编写良好的标准库算法永远不会比您自己的直接实现慢得多,除非您利用对数据细节的了解。