为什么GNU并行快速排序比合并排序慢? 我已经在C++标准库中测试OpenMP GNU并行排序算法的实用性,发现并行快速排序算法比合并算法快得多。在我的电脑上,Mergesort需要52秒来排序80亿个整数的向量,而Quicksort只需要不到8分钟。对其CPU使用情况的不科学检查表明,quicksort在大约20秒的时间内充分利用了并行性,然后它的其余运行只使用了2个线程(或%200 CPU)
我检查了算法的源代码,虽然我不能完全理解它。如果这不是原因,也许有人能向我解释一下为什么与mergesort相比,该算法如此缓慢?我本想联系算法的原始作者,但认为先在这里尝试更为礼貌 下面是一些代码,希望能够演示这个问题,如果我的运行不需要大量资源,您可以在命令行上指定要排序的元素数。我使用的是GCC 4.9:为什么GNU并行快速排序比合并排序慢? 我已经在C++标准库中测试OpenMP GNU并行排序算法的实用性,发现并行快速排序算法比合并算法快得多。在我的电脑上,Mergesort需要52秒来排序80亿个整数的向量,而Quicksort只需要不到8分钟。对其CPU使用情况的不科学检查表明,quicksort在大约20秒的时间内充分利用了并行性,然后它的其余运行只使用了2个线程(或%200 CPU),c++,parallel-processing,openmp,gnu,quicksort,C++,Parallel Processing,Openmp,Gnu,Quicksort,我检查了算法的源代码,虽然我不能完全理解它。如果这不是原因,也许有人能向我解释一下为什么与mergesort相比,该算法如此缓慢?我本想联系算法的原始作者,但认为先在这里尝试更为礼貌 下面是一些代码,希望能够演示这个问题,如果我的运行不需要大量资源,您可以在命令行上指定要排序的元素数。我使用的是GCC 4.9: #include <vector> #include <parallel/algorithm> #include <boost/date_time.hpp&
#include <vector>
#include <parallel/algorithm>
#include <boost/date_time.hpp>
#include <stdlib.h>
#include <iostream>
#include <omp.h>
#include <sstream>
const size_t DEFAULT_NUMBER = 8000000000;
int main(int argc, char **argv)
{
size_t number_of_elements = DEFAULT_NUMBER;
if(argc > 1 && argv[1] != 0)
{
number_of_elements = atoi(argv[1]);
}
std::vector<int> elements(number_of_elements);
srandom(10);
for(size_t i = 0; i < elements.size(); i++)
{
elements[i] = random();
}
boost::posix_time::ptime time = boost::posix_time::second_clock::local_time();
__gnu_parallel::sort(elements.begin(), elements.end(), __gnu_parallel::multiway_mergesort_tag());
std::cout << "Mergesort took: " << boost::posix_time::to_simple_string(boost::posix_time::second_clock::local_time() - time) << std::endl;
//Repopulate vector with random elements
srandom(10);
for(size_t i = 0; i < elements.size(); i++)
{
elements[i] = random();
}
time = boost::posix_time::second_clock::local_time();
__gnu_parallel::sort(elements.begin(), elements.end(), __gnu_parallel::quicksort_tag());
std::cout << "Quicksort took: " << boost::posix_time::to_simple_string(boost::posix_time::second_clock::local_time() - time) << std::endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
常量大小默认值=800000000;
int main(int argc,字符**argv)
{
元素的大小\u t编号\u=默认\u编号;
如果(argc>1&&argv[1]!=0)
{
元素的数量=原子(argv[1]);
}
std::向量元素(元素的数量);
随机数(10);
对于(size_t i=0;i
CFLAGS += -fopenmp -Ofast -march=native
它们加快了您的测试速度,但很抱歉,我没有足够的内核来复制您的结果。无论如何,允许本机CPU操作会影响数据访问序列化。我怀疑是因为分页和内存使用模式。您是否尝试使用不同的向量大小运行实验,并查看性能如何变化?我想是的因为快速排序一直使用同一个数组,所以线程需要序列化才能访问数组。MergeSort复制数组的一半,对它们进行排序,然后将它们合并,所以不需要数据访问序列化。@Svalorzen我尝试的数据是10亿个元素,20亿个,40亿个。1亿个元素是9秒OND代表Mergesort,54秒代表Quicksort,所以差距确实扩大了。@user3751940您是否尝试过以百万计的1k、10k、100k等等?您知道,以数十亿计的速度启动没有多大意义。您需要了解整个情况。您的内存大小是多少?我花了大量时间阅读它。有关排序及其标记的信息s似乎与我得到的编译错误不一致。无论如何,我最初通过-O2进行了优化,我添加了您的选项,但没有获得任何有意义的性能好处。您运行的是哪种机器/操作系统?我仍然无法复制您的结果-在我的机器上是快速排序(特别是平衡\u快速排序
版本)工作速度比MergeSort(排序40亿字节)快。但是,我看到了您在任务管理器中谈论的效果-CPU#1是100%,CPU#2是50%。可能是因为征服步骤中使用的线程数量有限-我看到了#pragma omp parallel num#u threads(2)
在两个版本的快速排序中。我使用的是双Intel Xeon E5-2670(总共16个物理内核)使用CentOS 6.4。我有120GB的RAM,所以我知道你是否会发现很难重现我的结果。我检查了代码并看到了这一点,但我一定是在非稳定排序中遗漏了它。如果前面提到的线程限制是原因,为什么会在征服阶段故意这样做?我想你在我的评论中是对的问题?