[英]Performance gap between sorting a list and a vector of structs. C++
我写了一个简单的C ++代码来检查数据排序的速度,以列表的形式表示,然后是矢量。
在列表的情况下,我得到时间为27秒。 对于矢量,我得到10秒。 为什么巨大的性能差距? 用于排序列表和向量的算法不一样吗? 即 归并排序?
编辑:我可能在最后一点错了。 据我所知,教科书在理论上描述排序算法时,似乎是在std::vector
意义上使用单词list
。 我不知道向量的排序算法如何与列表的排序算法不同,所以如果有人能够澄清那将是非常有用的。 谢谢。
//In this code we compare the sorting times for lists and vectors.
//Both contain a sequence of structs
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <iomanip>
using namespace std;
struct particle
{
double x;
double y;
double z;
double w;
bool operator<(const particle& a) const
{
return x < a.x;
}
};
int main(int argc, char *argv[])
{
int N=20000000;
clock_t start,stop;
vector<particle> myvec(N);
vector<particle>::iterator cii;
//Set vector values
for (cii = myvec.begin(); cii != myvec.end(); ++cii)
{
cii->x =1.0*rand()/RAND_MAX;
cii->y =1.0*rand()/RAND_MAX;
cii->z =1.0*rand()/RAND_MAX;
cii->w =1.0*rand()/RAND_MAX;
}
list<particle> mylist(N);
list<particle>::iterator dii;
//Set list values
for (cii=myvec.begin(),dii = mylist.begin(); dii != mylist.end() && cii!=myvec.end(); ++dii, ++cii)
{
dii->x =cii->x;
dii->y =cii->y;
dii->z =cii->z;
dii->w =cii->w;
}
//Sort the vector
start=clock();
sort(myvec.begin(),myvec.end());
stop=clock();
cout<<"Time for sorting vector "<<(stop-start)/(double) CLOCKS_PER_SEC<<endl;
//Sort the list
start=clock();
mylist.sort();
stop=clock();
cout<<"Time for sorting list "<<(stop-start)/(double) CLOCKS_PER_SEC<<endl;
return 0;
}
没有使用合并排序对std::vector
进行排序(在大多数实现中,标准没有指定算法)。
std::list
没有O(1)随机访问,所以它不能使用快速排序*等算法,这需要O(1)随机访问速度快(这也是为什么std::sort
不能在std::list
。)
有了这个,你将不得不使用前向迭代足够的算法,例如合并排序**。
另请参见: list.sort和std :: sort之间有什么区别?
*:libstdc ++实际上使用了introsort。
**:libstdc ++实际上使用了合并排序的变体
向量包含内存比列表更接近的内容。 这导致在排序期间更加缓存友好的访问模式。
我真的不是C ++程序员,但我的理解是std::vector
与std::list
具有不同的性能特征。 具体来说(正如@Martinho评论的那样):
std::vector
有O(1)随机访问,而std::list
则没有。
来自cplusplus.com (我确信那里有不那么粗略的引用,请随意加入):
矢量擅长:
- 按位置索引(恒定时间)访问各个元素。
- 以任何顺序迭代元素(线性时间)。
- 从末尾添加和删除元素(常量摊销时间)。
并且 :
...列出容器的优点:
- 在容器中的任何位置高效插入和移除元素(恒定时间)。
- 高效的移动元件和容器内的元件块,甚至是不同容器之间的元件(恒定时间)。
- 以正向或反向顺序(线性时间)迭代元素。
向量上的list::sort
和std::sort
不使用相同的算法。
std::sort
使用需要随机访问迭代器的排序算法,例如std::vector
所需的迭代器,而不是std::list
。
list::sort
专门用于列表; 它通常实现合并排序,不需要随机访问。
两种算法的比较总数是O(n log n)(我说不知道我的编译器的std::sort
实现使用的确切算法)。 交换的总数也是O(n log n),但是对于std::sort
,这意味着O(n log n)调用复制构造函数/赋值运算符,而对于list::sort
,它是指针操作。 你的结构太小,无法获得这种优势。 我假设只要你把一些非平凡的复制构造函数放入struct(也许std::string
就足够了), std::list
就会获胜。
编辑:一个std :: string成员初始化与随机双转换为文本似乎是关于我的机器上的收支平衡点(x86_64-linux,gcc 4.6.2)
向量将允许恒定时间元素交换以及恒定时间随机访问。 列表采用线性时间进行随机访问,同时(可能)触发指针更新的交换更多开销。 我的猜测就是做了一堆交换。 而且,向量在移动存储器中的大部分自身时更有效。
如果由于指针开销稍微减少而交换slist <>会比列表更快,我会很好奇。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.