列表排序和结构体向量排序之间的性能差距.c++
Performance gap between sorting a list and a vector of structs. C++
我写了一个简单的c++代码来检查排序数据的速度,以列表的形式表示,然后是向量。
在列表的情况下,我得到的时间为27秒。对于一个向量,我得到10秒。为什么会有如此巨大的表现差距?列表和向量排序的算法不是一样的吗?viz.归并排序?
EDIT:
最后一点我可能错了。据我所知,教科书在理论上描述排序算法时,似乎在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;
}
No a std::vector
不使用归并排序(在大多数实现;标准没有指定算法)。
std::list
没有O(1)随机访问,因此它不能使用像快速排序*这样需要O(1)随机访问的快速算法(这也是std::sort
不能在std::list
上工作的原因)
在这种情况下,您将不得不使用前向迭代算法,例如归并排序**。
并且归并排序通常比较慢[1][2]。
请参见:list和list之间的区别是什么。Sort和std:: Sort ?
*: libstdc++实际上使用了introsort。
**: libstdc++实际上使用了归并排序的一个变体
vector比list更靠近内存。这将在排序过程中产生更加缓存友好的访问模式。
我真的不是一个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
,这是一个指针操作。你的结构太小了,无法发挥这个优势。我认为,只要您将一些具有重要复制构造函数的东西放入结构中(也许std::string
就足够了),std::list
就会胜出。
vector将允许常量时间元素交换以及常量时间随机访问。随机访问列表需要线性时间,而(可能)有更多的指针更新交换开销。我猜排序是做了一堆掉期。此外,向量在内存中移动自己的大部分时更有效。
我很好奇,交换list<>是否会比交换list更快,因为指针开销稍微少一些。
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 二叉排序树无法编译
- OpenMP阵列性能较差
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- 递归列出所有目录中的C++与Python与Ruby的性能
- 对整个范围进行排序时,std::p artial_sort() 与 std::sort() 的性能?
- 比较两个排序的数字向量(性能优先)
- 基数排序256性能
- C++结构排序性能
- 与英特尔相比,GNU C++编译器在对向量进行排序时性能较差
- 三方快速排序需要更高的性能
- 提高循环缓冲区或堆排序性能
- C# 与 C/C++:我是否需要手动对结构字段进行排序以获得最佳性能
- 排序和扫描对报告中的性能问题
- STL排序在字符串矢量与字符串指针矢量上的性能比较
- 矢量排序/唯一/擦除与复制到无序集的性能
- 排序列表的最佳数据结构(性能)
- 列表排序和结构体向量排序之间的性能差距.c++
- 并行归并排序中的性能问题
- C++ vs Java - 选择排序性能