TBB task_arena & task_group 用于扩展parallel_for工作

TBB task_arena & task_group usage for scaling parallel_for work

本文关键字:task parallel for 工作 扩展 group arena TBB 用于      更新时间:2023-10-16

我正在尝试使用螺纹构建块task_arena。有一个简单的阵列" 0"。竞技场的线程将" 1"放在奇数位置的阵列中。主线程在偶数位置的阵列中放置" 2"。

/* Odd-even arenas tbb test */
#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>
#include <tbb/task_arena.h>
#include <tbb/task_group.h>
#include <iostream>
using namespace std;
const int SIZE = 100;
int main()
{
    tbb::task_arena limited(1); // no more than 1 thread in this arena
    tbb::task_group tg;
    int myArray[SIZE] = {0};
    //! Main thread create another thread, then immediately returns
    limited.enqueue([&]{ 
        //! Created thread continues here
        tg.run([&]{
            tbb::parallel_for(tbb::blocked_range<int>(0, SIZE), 
                [&](const tbb::blocked_range<int> &r)
                {
                    for(int i = 0; i != SIZE; i++)
                        if(i % 2 == 0)
                            myArray[i] = 1;
                }
            );
        });
    });
    //! Main thread do this work
    tbb::parallel_for(tbb::blocked_range<int>(0, SIZE), 
                [&](const tbb::blocked_range<int> &r)
                {
                    for(int i = 0; i != SIZE; i++)
                        if(i % 2 != 0)
                            myArray[i] = 2; 
                }
            );
    //! Main thread waiting for 'tg' group
    //** it does not create any threads here (doesn't it?) */
    limited.execute([&]{
        tg.wait();
    });
    for(int i = 0; i < SIZE; i++) {
        cout << myArray[i] << " ";
    }
    cout << endl;
    return 0;
}

输出是: 0 2 0 2 ... 0 2因此,有限的。有什么问题?有任何想法吗?谢谢。

您仅为一个线程创建了limited竞技场,默认情况下,此插槽保留给主线程。但是,进入这样的序列化领域将暂时将其并发级别提高到2(为了满足enqueue的"火和验证"的承诺),enqueue()不能保证对已提交任务的同步执行。因此,tg.wait()可以在tg.run()执行之前启动,因此,当创建工作线程,加入limited竞技场时,程序将不会等待,并用'1'填充数组(btw,整个数组在100个parallel_for tererations tererations中填充))。

因此,为了等待tg.run()完成,请改用limited.execute。但这将防止自动增强limited并发级别,并将任务推迟到主线程执行的tg.wait()

如果您想查看异步执行,请将Arena的并发设置为2手动:tbb::task_arena limited(2);
或禁用主线程的插槽保留:tbb::task_arena limited(1,0)(但请注意,这意味着竞技场中线程数量的动态平衡的其他开销)。

P.S。TBB没有确保线程来的点(与OpenMP不同)。只有enqueue方法可以保证创建至少一个工作线程,但它没有说明它何时到来。请参阅本地观察者功能,以获取线程实际加入竞技场时获得通知。