TBB用于不断变化的工作负载?

时间:2012-05-14 23:50:58

标签: c++ multithreading tbb

对不起,我似乎没有intel's TBB看起来很棒&支持,但我无法解决如何使用它,因为我想我不习惯在任务方面考虑并行性,而是将其视为线程。

我当前的工作负载有一个作业,它将工作发送到队列以保持处理(考虑递归,但不是自己调用它将工作发送到队列)。我在Java中使用它的方法是创建一个并发队列(非阻塞队列)和threadpoolexecutor,它使队列/发送工作回到它。但是现在我正在尝试用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个核心)。

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

2 个答案:

答案 0 :(得分:1)

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

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

我认为你的应用程序可以扩展,这意味着你从队列中的一些大量项目(比线程数远大)开始,而线程在进行处理时会在末尾添加足够的任务,这样就可以了每个人都有足够的工作,直到申请完成。

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

答案 1 :(得分:1)

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