我是英特尔TBB的新手。我正在使用concurrent_queue,以便在我的项目中实现细粒度的并行性。我几乎没有怀疑。这就是我的实施方式。
thread_fun(arguments) {
while(concurrent_queue.try_pop(v))
operation on v; //each thread executes its own operation(seperate v for each thread)
}
main() {
for(..)
concurrent_queue.push(); //fill the queue
_beginthreadex(..); //create 8 win32 threads and pass concurrent_queue as an argument
}
我明确提到了线程的数量。我读到TBB将根据处理器核心数创建线程。我怎样才能实现这一目标?所以我不需要使用_beginthreadex函数显式创建线程?
我是否通过使用concurrent_queue实现了细粒度的并行性?
任务级并行是什么意思?你如何用intel tbb实现任务级并行?我从队列中弹出元素。流行操作是否被视为一项任务?这意味着,所有弹出操作都被视为不同的任务。我用8个线程一次弹出8个元素。这意味着,我正在实现任务级并行性。我是对的吗?
如果我在四核处理器(支持8个线程)上将线程数增加到32,那么concurrent_queue如何工作?队列中是否同时执行了8个线程,或者同时执行了32个线程?
请帮帮我。
答案 0 :(得分:5)
TBB有很多部分。 Concurrent_queue只是一个可以由多个线程安全访问的队列。并发队列不是TBB的“细粒度并行”或“任务并行”部分的直接部分。 (虽然这些部分可以使用 concurrent_queue。)
使用tbb::parallel_for
在tbb中创建细粒度/任务并行度。请参阅该页面上的示例或at this stack overflow question。当您使用parallel_for时,tbb将负责所有线程创建,并且还将进行动态负载平衡。
Concurrent_queue根本不会创建任何并行性:它只允许多个线程安全地(并且相对有效地)访问同一个队列。它确保没有竞争条件。在您的示例中,您获得的并发数不超过8个线程。实际上:concurrent_queue是序列化对队列的访问。你的并行性来自你的“v on operations”。对concurrent_queue的访问应该被认为是开销。
您正在实例中实现基本类型的任务级并行性。我找到了this brilliant description of the difference between a task and a thread from a Stack Overflow answer by @Mitch Wheat:
任务是你想做的事。
线程是执行该任务的许多工作人员之一。
技术上更重要:任务不得阻止彼此等待。您的任务是您正在执行的“v on operations”。您正在实现任务级并行性。使用tbb::parallel_for
之类的东西的好处是它(a)自动为你启动线程,(b)尝试自动选择最适合用户系统核心数量的线程数量,(c)优化以减少将任务分配给线程的开销,以及(d)如果您的任务操作长度不相等,也会进行一些非常酷的动态负载平衡。
让我们区分并发和并行。您的机器有8个硬件线程。所以你的最大cpu并行度为8.我会使用术语并发来表示“如果你拥有一个具有无限内核数量的神奇处理器,你可以实现的最大并行度”。通常,创建更多线程的主要原因是您的线程正在进行大量长延迟的I / O操作。操作系统可以切换到其中一个额外的线程来执行cpu工作,而另一个线程正在等待磁盘/网络。