TBB task_arena&用于缩放parallel_for工作的task_group用法

时间:2015-05-05 19:52:39

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

我正在尝试使用Threaded Building Blocks 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.enque {tg.run {...}}块不起作用。 有什么问题?有任何想法吗?谢谢。

1 个答案:

答案 0 :(得分:2)

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

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

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

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