填充整数列表比填充整数向量快 100 倍
Populating a list of integers is 100 times faster than populating a vector of integers
我正在比较填充整数列表与整数向量所花费的时间。
每个向量和列表填充了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 " ;
}
有人可以向我解释为什么会发生这种情况???
我尝试使用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 高分辨率性能计数器来测量时间。
当然,我在优化的发布版本中进行了测试。
回循环中的随机数生成,并使用了比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() timen"
<< "--------------------------------------------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;
}
}
有人可以向我解释为什么会发生这种情况???
结果不是真实的,即填充整数列表并不比填充整数向量快 100 倍。您看到的是一个基准工件,由于注释中指出的代码错误。
如果您初始化变量并避免整数除法,那么您应该会看到不同的结果,例如,在我的机器上填充向量比填充列表快 3 倍(顺便说一句,调用vector::reserve()
对结果没有影响)。
相关:未初始化变量和编译器(GCC)的乐趣。
此外,不应将difftime(time_t, time_t)
与clock_t
值一起使用。
作为记录,在修复未初始化的变量问题和整数除法后,在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
因此,正如我所期望的那样,矢量更快。这不会对代码进行任何进一步的更改。
向量中的元素按顺序存储在连续的内存位置。最初,一些内存被分配给向量,随着您不断向向量添加更多元素,必须进行大量内存操作才能保留向量的这一属性。这些内存操作需要相当长的时间。
而在列表的情况下,head 存储第二个元素的地址,第三个元素的地址存储在第三个元素中,依此类推。这里不需要任何内存重新分配。
但与矢量相比,列表占用更多的存储内存。
如果向量的大小超过其容量,则需要重新分配向量。在这种情况下,必须将所有以前的值复制到新存储中。尝试使用vector::reserve
增加容量,以减少所需的重新分配。
- 如何反转整数参数包
- enum是C++中的宏变量还是整数变量
- 努力将整数转换为链表。不知道我在这里做错了什么
- 整数不会重复超过随机数
- 为什么我的 Char* 在填充整数后为空?
- 创建整数的 2D 数组,该数组将使用两个函数用随机数填充矩阵.我做错了什么?
- 错误:以增量方式填充向量时,表达式必须具有整数或无作用域枚举类型
- 如何计算未完全填充的数组中的整数
- 填充整数列表比填充整数向量快 100 倍
- 构造时,用整数序列填充向量
- 如果我有一个固定大小的填充ascii数字的char数组,我知道它指的是一个无符号整数,那么将其转换为无符号整数的最快方法
- 练习:用 C/C++ 中的整数填充向量
- 用整数填充自定义整数数组
- 如何在保持其顺序的同时填充整数数组
- 如何在没有多余整数的情况下填充整数之间的分隔符
- 用std::cout正确填充带零的负整数
- 更快的方式,然后我填充一个唯一的整数除了两个值的向量?c++
- 为什么堆栈上对齐的整数之间有 8 个字节的"0xcc"填充?C++ 32位视窗7
- 如何编写一个程序,从键盘上填充一个二维整数表a[3][2]
- 编写一个程序,填充从1到100的100个整数的数组