今天我决定对std::vector
和std::array
. 一般来说,我发现了我的预期:在每个短数组集合上执行任务比在集合等效向量上执行任务要快得多。
但是,我发现了一些意想不到std::vector
的事情:使用来存储数组集合比使用std::array
. 以防它是堆栈上大量数据的某些工件的结果,我还尝试将其分配为堆上的数组和堆上的 C 样式数组(但结果仍然类似于堆栈上的数组和数组向量)。
知道为什么std::vector
会超越(编译器有更多的std::array
编译时信息)吗?
gcc-4.7 -std=c++11 -O3
我使用(gcc-4.6 -std=c++0x -O3
也应该导致这个难题)编译。运行时间是使用bash
-nativetime
命令(用户时间)计算的。
代码:
#include <array>
#include <vector>
#include <iostream>
#include <assert.h>
#include <algorithm>
template <typename VEC>
double fast_sq_dist(const VEC & lhs, const VEC & rhs) {
assert(lhs.size() == rhs.size());
double result = 0.0;
for (int k=0; k<lhs.size(); ++k) {
double tmp = lhs[k] - rhs[k];
result += tmp * tmp;
}
return result;
}
int main() {
const std::size_t K = 20000;
const std::size_t N = 4;
// declare the data structure for the collection
// (uncomment exactly one of these to time it)
// array of arrays
// runtime: 1.32s
std::array<std::array<double, N>, K > mat;
// array of arrays (allocated on the heap)
// runtime: 1.33s
// std::array<std::array<double, N>, K > & mat = *new std::array<std::array<double, N>, K >;
// C-style heap array of arrays
// runtime: 0.93s
// std::array<double, N> * mat = new std::array<double, N>[K];
// vector of arrays
// runtime: 0.93
// std::vector<std::array<double, N> > mat(K);
// vector of vectors
// runtime: 2.16s
// std::vector<std::vector<double> > mat(K, std::vector<double>(N));
// fill the collection with some arbitrary values
for (std::size_t k=0; k<K; ++k) {
for (std::size_t j=0; j<N; ++j)
mat[k][j] = k*N+j;
}
std::cerr << "constructed" << std::endl;
// compute the sum of all pairwise distances in the collection
double tot = 0.0;
for (std::size_t j=0; j<K; ++j) {
for (std::size_t k=0; k<K; ++k)
tot += fast_sq_dist(mat[j], mat[k]);
}
std::cout << tot << std::endl;
return 0;
}
注意 1:所有版本都打印相同的结果。
NB 2:并且只是为了证明 , 和 之间的运行时差异std::array<std::array<double, N>, K>
不仅仅是std::vector<std::array<double, N> >
分配std::vector<std::vector<double> >
时的分配/初始化,简单分配集合的运行时间(即注释掉 的计算和打印tot
)是 0.000s、0.000s、和 0.004s,分别。
NB 3:每个方法都是单独编译和运行的(不是在同一个可执行文件中背靠背计时),以防止缓存中的不公平差异。
NB 4:
数组数组的组装:http: //ideone.com/SM8dB
数组向量的组装:http: //ideone.com/vhpJv
向量的组装:http: //ideone.com/RZTNE
NB 5:为了绝对清楚,我绝不打算批评 STL。一个绝对喜欢的 STL,不仅我经常使用它,而且有效使用的细节教会了我很多 C++ 微妙而伟大的特性。相反,这是一种智力追求:我只是在安排时间来学习高效 C++ 设计的原则。
此外,责怪 STL 是不合理的,因为很难对运行时差异的病因进行反卷积:启用优化后,编译器优化可能会减慢而不是加快代码速度。在关闭优化的情况下,它可能来自不必要的复制操作(将被优化并且永远不会在生产代码中执行),这可能比其他数据类型更偏向某些数据类型。
如果您像我一样好奇,我希望您能帮助解决这个问题。