线程构建块与pthreads相结合

时间:2012-12-12 01:09:13

标签: c++ parallel-processing pthreads openmp tbb

我有一个包含需要处理的元素的队列。我想并行处理这些元素。将是需要同步的每个元素的一些部分。在任何时间点都可以有最大 num_threads 运行线程。

我会提供模板,让您了解我想要实现的目标。

queue q

process_element(e)
{
    lock()
    some synchronized area
    // a matrix access performed here so a spin lock would do
    unlock()
    ...
    unsynchronized area
    ...
    if( condition )
    {
        new_element = generate_new_element()
        q.push(new_element) // synchonized access to queue
    }
}

process_queue()
{
    while( elements in q ) // algorithm is finished condition
    {
         e = get_elem_from_queue(q) // synchronized access to queue
         process_element(e)
    }
}

我可以使用

  • 并行线程
  • 的openmp
  • intel thread building blocks

我遇到的主要问题

  • 确保在任何时候我都有 num_threads 正在运行的主题
  • 队列中使用的轻量级同步方法

我的计划是针对队列容器的intel tbb concurrent_queue。但是,我能使用pthreads函数(互斥,条件)吗?让我们假设这是有效的(它应该)。那么,我如何使用pthreads在一个时间点获得max num_threads?我想创建一次线程,然后,在一个元素进程之后,访问队列并获取下一个元素。然而,如果更复杂,因为我无法保证如果队列中没有元素,算法就完成了。

我的问题

在我开始实现之前,我想知道是否有一种简单的方法来使用intel tbb或pthreads来获得我想要的行为?更准确地说是并行处理队列中的元素

注意:我尝试过使用但没有成功。

3 个答案:

答案 0 :(得分:1)

首先,pthreads为您提供了难以摆脱的便携性。您的问题似乎如下:让我们知道这些是不是真的,因为答案会改变: 1)您有一个运行代码的多核处理器 2)由于(1)

,您希望不超过 num_threads 个主题

假设上述情况属实,以下方法可能适合您:

  1. 使用pthread_create创建 num_threads pthreads
  2. (可选)将每个线程绑定到不同的核心
  3. q.push(new_element)原子地将new_element添加到队列中。 pthreads_mutex_lock和pthreads_mutex_unlock可以帮到你。例如:http://pages.cs.wisc.edu/~travitch/pthreads_primer.html
  4. 使用pthreads_mutexes排队元素
  5. 终止是棘手的 - 一种方法是将一个TERMINATE元素添加到队列中,该队列在出队时导致dequeuer排队另一个TERMINATE元素(用于下一个dequeuer),然后终止。最终会在队列中添加一个额外的TERMINATE元素,您可以通过让所有线程完成后命名的线程将其取消来删除。
  6. 根据您在队列中添加/删除元素的频率,您可能希望使用比pthread_mutex _...更轻的重量来排队/取消元素。您可能希望使用更具机器特定的构造。

答案 1 :(得分:0)

TBB与其他线程包兼容。

TBB还强调可扩展性。因此,当您将程序移植到双核到四核时,您无需调整程序。通过数据并行编程,在添加处理器时,程序性能会提高(缩放)。

Cilk Plus也是另一个提供良好结果的运行时。

www.cilkplus.org

由于pThreads是一个低级别的主题库,你必须决定应用程序需要多少控制,因为它确实提供了灵活性,但在程序员工作量,调试时间和维护成本方面成本很高。

答案 2 :(得分:0)

我的建议是查看tbb::parallel_do。它被设计为并行处理容器中的元素,即使容器本身不是并发的;即parallel_do正确使用std::queue而无需任何用户同步(当然,您仍然需要保护process_element()内的矩阵访问权限。此外,使用parallel_do您可以添加更多内容因为process_element()创建并添加新元素到工作队列中,所以看起来就像你需要的那样工作(唯一的警告是新添加的工作将立即被处理,不像放入一个会推迟的队列处理所有“较旧”项目之后)。此外,您不必担心终止:parallel_do将在处理完所有初始队列项目和新项目时自动完成。

但是,如果除了计算本身之外,工作队列可以同时从另一个源(例如来自I / O处理线程)馈送,那么parallel_do是不合适的。在这种情况下,查看parallel_pipeline或更好的TBB流程图可能是有意义的。

最后,应用程序可以使用TBB控制活动线程的数量,但这不是推荐的方法。