TBB task_arena & task_group usage for scaling parallel_for work
我正在尝试使用 Threaded Building Blocks task_arena。有一个充满”0″的简单数组。 Arena 的线程将”1″放入数组中的奇数位置。主线程将’2’放在偶数位置的数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
/* 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{…}} 块不起作用。
有什么问题?有任何想法吗?谢谢。
你只为一个线程创建了 limited arena,默认情况下这个槽是为主线程保留的。虽然,进入这样的序列化领域会暂时将其并发级别提高到 2(为了满足 enqueue 的”即发即弃”Promise),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;}} 但接下来(对于主线程)类似于 while(flag) tg.wait(); /* yes, it is active waiting, but, according to your answer, there is no way to force main thread to wait for tg to finish its work, because the time, when tg.run will actually start is unpredictable. Isn’t it?*/ (2)使用 tbb::task_arena limited(2) 然后 limited.execute{tg.run{…}} next tg.wait()
-
是的,这是正确的。只是不要忘记将标志声明为原子
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/268953.html