最近几天,我一直在复习排序算法,并遇到了一个找不到最佳解决方案的情况。我编写了一个基本的快速排序实现,并希望通过并行执行来提高其性能。
我所拥有的是:
template <typename IteratorType>
void quicksort(IteratorType begin, IteratorType end)
{
if (distance(begin, end) > 1)
{
const IteratorType pivot = partition(begin, end);
if (distance(begin, end) > 10000)
{
thread t1([&begin, &pivot](){ quicksort(begin, pivot); });
thread t2([&pivot, &end](){ quicksort(pivot + 1, end); });
t1.join();
t2.join();
}
}
}
虽然这比朴素的“无线程”实现效果更好,但它有严重的限制,即:
- 如果要排序的数组太大或递归层数过深,系统可能会耗尽线程,导致执行失败。
- 在每个递归调用中创建线程的成本可能是可以避免的,特别是考虑到线程不是无限的资源。
我想使用线程池来避免晚期线程创建,但我面临另一个问题:
- 我创建的大部分线程在开始时都完成了它们的工作,然后在等待子调用完成时什么也不做。这导致许多线程只是等待子调用完成,这似乎相当次优。
是否有一种技术/实体可以用来避免浪费线程(允许它们的重新使用)?
我可以使用boost或任何C++11设施。
join
-- 相反,你创建任务并获取std::future
。要完成的任务将被分派到线程中,生成答案并退出。对于你的代码,你需要划分,创建一个任务来排序前半部分和后半部分,然后安排 "我完成了" 消息 当这两个任务都完成时(可能通过在两个future
上使用then
机制或从任务池获得帮助)。然后你的代码将退出,返回构造的future
。 - Yakk - Adam Nevraumont