如何使用具有递归模板函数的线程

时间:2013-02-24 02:08:23

标签: c++ multithreading templates c++11

我一直在尝试使用线程优化排序算法(quicksort)。我知道它在std :: sort()实现中已经相当不错了,但是我试图通过计算机上的优化来击败它,并同时了解线程。

所以,我的问题是,如何在递归快速排序函数中使用线程?

这里的功能(删除了不重要的问题):

template <typename T>
void quicksort(T arr[], const int &size, const int &beginning, const int &end)
{
    // Algorithm here
    thread t1(quicksort, arr, size, beginning, slow - 1);
    thread t2(quicksort, arr, size, slow + 1, end);
}

如果我错了,你最终需要更多代码,请告诉我,我会更新它。

我使用的是Visual Studio 2012,截至目前,该错误指出:

error C2661: 'std::thread::thread' : no overloaded function takes 5 arguments

我也试过在每个参数上调用ref(arr)等,但是我得到了同样的错误。

编辑: 在通过@mfontanini尝试解决方案后,我可以编译没有错误,但在运行时,我得到:

Debug Error!

Program: ...sktop\VisualStudio\Projects\SpeedTester\Debug\SpeedTester.exe

R6010
- abort() has been called


(Press Retry to debug the application)

重复一遍又一遍。最终,它以代码3退出。

2 个答案:

答案 0 :(得分:2)

您需要明确指出哪个是T模板参数:

thread t1(&quicksort<T>, arr, size, beginning, slow - 1);

否则编译器会看到您指的是函数模板,而不是指哪个特定的特化;它不能无处推断T

答案 1 :(得分:0)

您的主要问题可能是您需要join()生成的thread。如果线程对象在没有事先join()detach()实施调用std::terminate()的情况下被破坏。

您不需要detach(),因为您需要知道所有部分排序都已完成才能完成整体排序,因此join是正确的事情。

此外,还有一些事情可以改进:

  • 您不应该通过引用传递int。对于简单的标量类型,传递值更有效,并且从其他线程引用局部变量通常不是一个好主意(除非你有充分的理由和协议)
  • 你开始的线程太多了。分区后,您需要两个子线程用于两个子排序,但是您有三个:当前线程也继续运行,因此您应该只创建一个新线程并在当前线程中执行另一个子排序。 (完成后,join()另一部分。)
  • 当分区变小时,您不应该继续创建新线程。为快速排序设置一个截止大小通常是个好主意,并且对于较小的大小使用非递归(如插入排序)的东西,因为递归开销变得高于算法复杂性的好处。类似的截止对于并发排序更为重要:线程的开销远远高于简单的递归调用,并且对于小的(和附近的)分区,线程将开始经常访问相同的缓存行,从而减慢速度甚至更多。
  • 创建没有限制的线程通常不是一个好主意。这最终会遇到平台限制。您可能希望限制要使用的线程数(使用原子计数器)或使用类似std::async的默认启动策略,以避免启动比平台可以处理的更多线程。