填充整数列表比填充整数向量快 100 倍
Posted
技术标签:
【中文标题】填充整数列表比填充整数向量快 100 倍【英文标题】:Populating a list of integers is 100 times faster than populating a vector of integers 【发布时间】:2014-02-17 11:29:32 【问题描述】:我将填充整数列表与整数向量所花费的时间进行比较。
每个向量和列表都填充了 1000 万个随机整数,并且该实验重复 100 次以找到平均值。
令我惊讶的是,填充列表比填充整数向量快大约 100 倍。我希望填充整数向量要快得多,因为向量在内存中是连续的并且插入要快得多。
如何填充列表比填充向量快 100 倍而不是 10 倍。我确信我错过了一些导致这种情况的概念或想法
这是我用来生成结果的代码
#include <iostream>
#include <sstream>
#include <list>
#include <vector>
#include <ctime>
#include <time.h>
using namespace std;
int main()
list<int> mylist;
vector<int> myvector;
srand(time(NULL));
int num;
clock_t list_start;
clock_t list_end;
clock_t list_totaltime;
for (int i=0;i<100;i++)
list_start = clock();
for (int i = 0 ; i < 10000000 ; i++ ) // 10 million
num = rand() % 10000000 ;
mylist.push_back(num);
list_end = clock();
list_totaltime += difftime(list_end,list_start);
mylist.clear();
cout << list_totaltime/CLOCKS_PER_SEC/100;
cout <<" List is done ";
cout << endl
<< endl;
clock_t vector_start;
clock_t vector_end;
clock_t vector_totaltime;
for (int i=0;i<100;i++)
vector_start = clock();
for (int i = 0 ; i < 10000000 ; i++ ) // 10 million times
num = rand() % 10000000 ;
myvector.push_back(num);
vector_end = clock();
vector_totaltime += difftime(vector_end,vector_start);
myvector.clear();
cout << vector_totaltime/CLOCKS_PER_SEC/100;
cout << " Vector is done " ;
有人可以向我解释为什么会这样吗???
【问题讨论】:
你需要初始化list_totaltime
和vector_totaltime
。提高编译器警告级别。
当列表大小增加时,不需要重新定位已经定位的内容,这与向量不同(由于连续性)。
它可以防止你的输出完全是垃圾。
你也有整数除法。所以,当我运行你的代码并修复初始化问题时,我得到了0
。
@juanchopanza 你将 list_totaltime 和 vector_totaltime 初始化为什么???
【参考方案1】:
我尝试使用 VS2013 C++ 编译器,std::vector
比 std::list
快得多(正如我所料)。
我得到了以下结果:
Testing STL vector vs. list push_back() time -------------------------------------------- Testing std::vector...done. std::vector::push_back(): 89.1318 ms Testing std::list...done. std::list::push_back(): 781.214 ms
我使用 Windows 高分辨率性能计数器来测量时间。 当然,我在 optimized release build 中进行了测试。
我还重构了推回循环之外的随机数生成,并使用了more serious random number technique than rand()
。
您使用clock()
的方法是否适合测量执行时间?
您使用的是什么 C++ 编译器?您是否测试了优化构建?
可编译的测试代码如下:
// Testing push_back performance: std::vector vs. std::list
#include <algorithm>
#include <exception>
#include <iostream>
#include <list>
#include <random>
#include <vector>
#include <Windows.h>
using namespace std;
long long Counter()
LARGE_INTEGER li;
QueryPerformanceCounter(&li);
return li.QuadPart;
long long Frequency()
LARGE_INTEGER li;
QueryPerformanceFrequency(&li);
return li.QuadPart;
void PrintTime(const long long start, const long long finish,
const char * const s)
cout << s << ": " << (finish - start) * 1000.0 / Frequency() << " ms" << endl;
int main()
try
cout << endl
<< "Testing STL vector vs. list push_back() time\n"
<< "--------------------------------------------\n"
<< endl;
const auto shuffled = []() -> vector<int>
static const int kCount = 10 * 1000 * 1000;
vector<int> v;
v.reserve(kCount);
for (int i = 1; i <= kCount; ++i)
v.push_back((i % 100));
mt19937 prng(1995);
shuffle(v.begin(), v.end(), prng);
return v;
();
long long start = 0;
long long finish = 0;
cout << "Testing std::vector...";
start = Counter();
vector<int> v;
for (size_t i = 0; i < shuffled.size(); ++i)
v.push_back(shuffled[i]);
finish = Counter();
cout << "done.\n";
PrintTime(start, finish, "std::vector::push_back()");
cout << endl;
cout << "Testing std::list...";
start = Counter();
list<int> l;
for (size_t i = 0; i < shuffled.size(); ++i)
l.push_back(shuffled[i]);
finish = Counter();
cout << "done.\n";
PrintTime(start, finish, "std::list::push_back()");
catch (const exception& ex)
cout << "\n*** ERROR: " << ex.what() << endl;
【讨论】:
我是在 qunicy 2005 编译器上完成的,非常怀疑是否有为此构建的优化工具【参考方案2】:有人可以向我解释为什么会这样吗???
结果不是真实的,即填充整数列表不是比填充整数向量快 100 倍。由于comments 中的代码pointed out 中的错误,您看到的是基准工件。
如果您初始化变量并避免整数除法,那么您应该会看到不同的结果,例如,在我的机器上填充向量比填充列表快 3 倍(顺便说一句,调用 vector::reserve()
对结果没有影响)。
相关:Fun with uninitialized variables and compiler (GCC).
此外,您不应将 difftime(time_t, time_t)
与 clock_t
值一起使用。
【讨论】:
【参考方案3】:作为记录,在修复未初始化的变量问题和整数除法之后,在 x86_64 和以下标志上运行使用 gcc 4.7.3 编译的优化构建
g++ -Wall -Wextra -pedantic-errors -pthread -std=c++11 -O3
我明白了
0.2 List is done
0.07 Vector is done
所以,正如我所预料的那样,向量更快。这无需对代码进行任何进一步的更改。
【讨论】:
【参考方案4】:向量中的元素按顺序存储在连续的内存位置中。最初为向量分配了一些内存,当您不断向向量添加更多元素时,必须进行大量 内存操作 才能保留 vector 的此属性。这些内存操作需要相当长的时间。
而在 list 的情况下,头部存储第二个元素的地址,第三个元素的地址存储在第三个元素中,依此类推。这里不需要任何内存重新分配。
但与向量相比,列表需要更多的存储内存。
【讨论】:
【参考方案5】:如果向量的大小超过其容量,则需要重新分配向量。在这种情况下,所有以前的值都必须复制到新存储中。
尝试使用vector::reserve
增加容量以减少所需的重新分配。
【讨论】:
以上是关于填充整数列表比填充整数向量快 100 倍的主要内容,如果未能解决你的问题,请参考以下文章