【问题标题】:TBB task_arena & task_group usage for scaling parallel_for workTBB task_arena 和 task_group 用于扩展 parallel_for 工作
【发布时间】:2015-05-05 19:52:38
【问题描述】:

我正在尝试使用 Threaded Building Blocks task_arena。有一个充满“0”的简单数组。 Arena 的线程将“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.enque{tg.run{...}} 块不起作用。 有什么问题?有任何想法吗?谢谢。

【问题讨论】:

    标签: c++ multithreading c++11 concurrency tbb


    【解决方案1】:

    你只为一个线程创建了limited arena,默认情况下这个槽是为主线程保留的。虽然,进入这样一个序列化领域会暂时将其并发级别提高到 2(为了满足enqueue 的“即发即弃”承诺),enqueue() 不保证提交任务的同步执行。所以,tg.wait() 可以在 tg.run() 执行之前启动,因此程序在创建工作线程时不会等待,加入 limited 竞技场,并用 '1' 填充数组(顺便说一句,整个数组都被填充了) 100 个 parallel_for 迭代中的每一个)。

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

    如果你想看到异步执行,手动设置arena的并发为2:tbb::task_arena limited(2);
    或禁用主线程的插槽保留:tbb::task_arena limited(1,0)(但请注意,这意味着动态平衡 arena 中的线程数量会产生额外的开销)。

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

    【讨论】:

    • 谢谢你,Антон!那么,我是否正确,有 两种 方法:(1) 使用tbb::task_arena limited(1) /*enqueue will enhance concurrency level from 1 to 2*/,然后使用limited.enqueue{tg.run{/* some work */ flag = 1;}} 但接下来(对于主线程)类似于@987654336 @(2) 使用tbb::task_arena limited(2) 然后limited.execute{tg.run{...}} 下一个tg.wait()
    • 是的,没错。只是不要忘记将标志声明为原子
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多