0

很抱歉,我似乎没有得到英特尔的 TBB,它看起来很棒且受支持,但我无法理解如何使用它,因为我想我不习惯在任务方面考虑并行性,而是看到它作为线程。

我当前的工作负载有一项将工作发送到队列以继续处理的作业(考虑递归,但不是调用自身,而是将工作发送到队列)。我在 Java 中进行这项工作的方式是创建一个并发队列(非阻塞队列)和线程池执行器,用于处理队列/将工作发送回它。但是现在我正在尝试在 C++ 中做类似的事情,我发现 TBB 可以创建池,但它的方法非常不同(Java 线程似乎只要它们在队列中工作就可以继续工作,但 TBB 似乎打破了任务开头)。

这是我所做的一个简单的Java示例(在此之前我设置了我想要的线程数等):

static class DoWork implements Callable<Void> {
    // queue with contexts to process
    private Queue<int> contexts;

    DoWork(Context request) {
        contexts = new ArrayDeque<int>();
        contexts.add(request);
    }

    public Void call() {
        while(!contexts.isEmpty()) {
            //do work 
            contexts.add(new int(data)); //if needs to be send back to the queue to do more work
        }
    }
}

我确信它可以在 TBB 中做到这一点,但我只是不确定如何,因为它似乎在我发送它时破坏了我的工作。因此,如果队列中有 2 个项目,它可能只会启动 2 个线程,但不会随着更多工作的进入而增长(即使我有 8 个内核)。

有人可以帮助我了解如何完成我的任务,还可以建议一种更好的方式来思考来自使用 Java 的线程环境的 TBB(我也不忠于 TBB,所以如果有更容易/更好的东西,那么我很乐意学习它。我只是不喜欢 c++ 线程池,因为它似乎没有积极开发)?

4

2 回答 2

1

基于具有用于并行处理的项目队列的方法,其中每个线程仅从队列中弹出一个项目并继续(并可能在某个时刻将新项目添加到队列的末尾)从根本上是错误的,因为它限制了并行性应用程序。队列成为单点同步,线程需要等待才能访问下一个要处理的项目。在实践中,当任务(每个项目的处理作业)非常大并且需要不同的时间来完成时,这种方法有效,与(大多数)线程同时完成并进入队列时相比,允许队列较少竞争以便他们处理下一个项目。

如果您正在编写一段可重用的代码,则无法保证任务足够大或大小不同(执行时间)。

我假设您的应用程序可以扩展,这意味着您从队列中的大量项目(远大于线程数)开始,而线程进行处理时,它们会在最后添加足够的任务,以便有足够的工作所有人,直到申请完成。

如果是这种情况,我宁愿建议您保留项目的两个线程安全向量(例如 TBB 的 concurrent_vectors)以实现互换性。您从一个向量(您的初始项目集)开始,然后 enque() 一个任务(我认为它在 TBB 参考手册的第 12 章中的某处进行了描述),它在项目的初始向量上执行 parallel_for。在处理第一批时,您会将新项目 push_back 到第二个 concurrent_vector 上,当您完成第一个时,您 enque() 在第二个向量上使用 parallel_for 的任务并开始将新项目推回第一个. 您可以尝试更好地重叠项目的并行处理,方法是使用三个向量而不是两个向量,并在它们之间逐渐移动,同时仍有足够的工作让所有线程保持忙碌。

于 2012-05-15T21:00:06.167 回答
1

您正在尝试做的正是 TBB 的parallel_do设计目的。调用的“body”parallel_do传递了一个“feeder”参数,您可以在处理任务时执行该参数以在当前完成feeder.add(...some new task...)之前创建新任务以执行。parallel_do

于 2012-05-15T23:02:47.360 回答