在c+中使用多线程进行快速排序+; 我在代码中使用多线程< /C> > C++实现了代码> > QuaskSux程序。p>
组合任务的方法是维护一个任务队列。每个 自由线程从公文包中选择一个任务,必要时执行它 生成新的子任务并将其放入公文包 但我不确定什么是对的!在我看来,在一个在c+中使用多线程进行快速排序+; 我在代码中使用多线程< /C> > C++实现了代码> > QuaskSux程序。p>,c++,multithreading,sorting,synchronization,quicksort,C++,Multithreading,Sorting,Synchronization,Quicksort,组合任务的方法是维护一个任务队列。每个 自由线程从公文包中选择一个任务,必要时执行它 生成新的子任务并将其放入公文包 但我不确定什么是对的!在我看来,在一个线程中,算法的运行速度比两个或四个线程快。我能把同步搞砸吗 谢谢任何人帮助我 代码: #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 #包括 使用名称空间std; //打印阵列 模板 无效打印(常量向量和arr) { 对于(大小i=0;i
线程
中,算法的运行速度比两个或四个线程
快。我能把同步搞砸吗
谢谢任何人帮助我
代码:
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
//打印阵列
模板
无效打印(常量向量和arr)
{
对于(大小i=0;i cout影响性能的因素远不止你在这个问题上抛出了多少线程。其中
- 您需要实际的并发性,而不仅仅是多个线程
- 标准的快速排序具有很好的引用局部性,特别是当分区大小变小时,但您的技术会丢掉很多引用局部性,因为在每次分区时,对给定数组元素的责任很可能会被交换到不同的线程
- 此外,互斥操作并不特别便宜,当分区变小时,您开始执行相当多与实际排序量相关的操作
- 使用比物理内核更多的线程是没有意义的。四个线程可能不会太多,但这取决于您的硬件
以下是一些可以提高多线程性能的方法:
在方法quick_sort()
中,在实际排序过程中,不要像当前一样保持互斥锁q_互斥锁
锁定(您使用的unique_lock
构造函数锁定互斥锁,并且在unique_lock
的生命周期内不会解锁它)
对于小于某个阈值大小的分区,请切换到普通的递归技术。您必须进行测试以找到一个好的特定阈值;也许它需要可调
在每个分区中,让每个线程只将其中一个子分区发布到公文包中;让它递归地处理另一个子分区——或者更好地说,迭代地处理。事实上,将它设置为您发布的较小的子分区,因为这样可以更好地限制公文包的大小
你也可以考虑增加你运行测试的元素的数量。100000并不是那么多,你可能会看到较大的问题的不同的性能特征。1000000个元素对于现代硬件的测试并不完全是不合理的。
在我看来,你应该捕获组合任务的行为。他进入了一个班级
template <typename TASK, unsigned CONCURRENCY>
class Portfolio {
std::array<std::thread, CONCURRENCY> workers_;
std::deque<TASK> tasks_;
std::mutex m_;
std::condition_variable cv_;
std::atomic<bool> quit_;
void work () {
while (!quit_) {
TASK t = get();
if (quit_) break;
t();
}
}
TASK get () {
std::unique_lock<std::mutex> lock(m_);
while (tasks_.empty()) {
cv_.wait(lock);
if (quit_) return TASK();
}
TASK t = tasks_.front();
tasks_.pop_front();
if (!tasks_.empty()) cv_.notify_one();
return t;
}
public:
void put (TASK t) {
std::unique_lock<std::mutex> lock(m_);
tasks_.push_back(t);
cv_.notify_one();
}
Portfolio ();
~Portfolio ();
};
不幸的是,这种制定并行快速排序的方法不太可能产生很大的加速。您要做的是并行化分区任务,这至少需要一个单线程计算过程(包括数据比较和交换),然后才能开始并行化
首先将数组划分为工作大小
子数组,对每个子数组并行执行快速排序,然后合并结果以创建排序向量可能会更快。Hm,这行唯一锁定
是否将并行代码转换为连续的?ru上的问题也是一样。所以,我想指出at并行排序操作已经存在:嘿!你解决问题了吗?另外,他的快速排序算法总是在一个线程上运行,所以其他线程基本上什么也不做。谢谢你的建议!@Rakete1111那么如何修改代码以使其他线程获得收益呢?我不明白。@rekrut,我已将我的答案更新为address t他给出了1111分,谢谢你们的回答!!
template <typename TASK, unsigned CONCURRENCY>
class Portfolio {
std::array<std::thread, CONCURRENCY> workers_;
std::deque<TASK> tasks_;
std::mutex m_;
std::condition_variable cv_;
std::atomic<bool> quit_;
void work () {
while (!quit_) {
TASK t = get();
if (quit_) break;
t();
}
}
TASK get () {
std::unique_lock<std::mutex> lock(m_);
while (tasks_.empty()) {
cv_.wait(lock);
if (quit_) return TASK();
}
TASK t = tasks_.front();
tasks_.pop_front();
if (!tasks_.empty()) cv_.notify_one();
return t;
}
public:
void put (TASK t) {
std::unique_lock<std::mutex> lock(m_);
tasks_.push_back(t);
cv_.notify_one();
}
Portfolio ();
~Portfolio ();
};
template <typename T, unsigned WORK_SIZE, typename PORTFOLIO>
QuickSortTask {
std::reference_wrapper<PORTFOLIO> portfolio_;
std::reference_wrapper<std::vector<T>> arr_;
int start_;
int end_;
QuickSortTask (PORTFOLIO &p, std::vector<T> &a, int s, int e)
: portfolio_(p), arr_(a), start_(s), end_(e)
{}
void operator () () {
if ((end_ - start_) > WORK_SIZE) {
int p = partition(arr_, start_, end_);
portfolio_.put(QuickSortTask(portfolio_, arr_, start_, p-1));
portfolio_.put(QuickSortTask(portfolio_, arr_, p+1, end_));
} else {
regular_quick_sort(arr_, start_, end_);
}
}
};