1

我有一个包含需要处理的元素的队列。我想并行处理这些元素。这将是需要同步的每个元素的一些部分。在任何时间点都可以有最大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)
    }
}

我可以用

  • 线程
  • 开放式
  • 英特尔线程构建块

我遇到的主要问题

  • 确保在任何时候我都有最大num_threads运行线程
  • 用于队列的轻量级同步方法

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

我的问题

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

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

4

3 回答 3

1

首先,pthreads 为您提供了难以摆脱的可移植性。从您的问题来看,以下内容似乎是正确的 - 如果这些不正确,请告诉我们,因为答案将会改变:1)您有一个运行代码的多核处理器 2)您想要由于 (1),线程数不超过num_threads

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

  1. 使用 pthread_create创建num_threads 个pthread
  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 元素,它在出队时会导致出队者排队另一个 TERMINATE 元素(用于下一个出队者)然后终止。您最终会在队列中得到一个额外的 TERMINATE 元素,您可以通过在所有线程完成后让一个命名线程将其出列来删除它。

根据您从队列中添加/删除元素的频率,您可能希望使用比 pthread_mutex_... 更轻的东西来使元素入队/出队。这是您可能想要使用更特定于机器的构造的地方。

于 2012-12-12T18:05:43.250 回答
0

我的建议是看看tbb::parallel_do。它旨在并行处理来自容器的元素,即使容器本身不是并发的;ieparallel_do可以在std::queue没有任何用户同步的情况下正常工作(当然,您仍然需要保护内部的矩阵访问process_element()。此外,parallel_do您可以动态添加更多工作,这看起来就像您需要的那样,process_element()创建并向工作队列(唯一要注意的是新添加的工作将立即处理,不像放入队列会推迟处理直到所有“旧”项目之后)。此外,您不必担心终止:parallel_do将自动完成一旦处理了所有初始队列项目和动态创建的新项目。

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

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

于 2012-12-20T20:07:39.680 回答
0

TBB 与其他线程包兼容。

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

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

www.cilkplus.org

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

于 2012-12-12T18:33:31.800 回答