Tbb并行管道对令牌的原位修改

时间:2013-02-28 22:51:01

标签: c++ tbb

我想使用tbb管道来并行处理令牌。

但是我不需要在中间过滤器中释放和重新分配令牌。可以简单地就地修改并返回它吗?例如,我想这样做:

class MiddleFilter
{
SomeClass* operator() (SomeClass* input)
{
input->somevalue *= 2;
return input;
}
}

并致电

tbb::parallel_pipeline(nbtoken, someinputfilter 
& tbb::make_filter<SomeClass*, SomeClass*>(tbb::filter::parallel, MiddleFilter())
& someoutputfilter)

SomeClass将在输入和输出过滤器中分配和释放。

1 个答案:

答案 0 :(得分:2)

是的,允许对传递给过滤器的对象进行原位修改,并且在处理复制昂贵的对象时经常有用。我在使用parallel_pipeline并行化Bzip2时已经这样做了。就TBB而言,示例中的指针“输入”只是TBB不试图解释的值。

还有一个技巧我有时用来保存第一个/最后一个过滤器中的分配/释放。如果第一个和最后一个过滤器是串行过滤器,并且第一个过滤器生成与最后一个过滤器消耗的相同类型的对象,则可以使用循环对象队列来回收对象。缓冲区的大小必须是max_number_of_live_tokens(parallel_pipeline的第一个参数)。第一个过滤器可以通过出列来分配对象;最后一个阶段可以通过排队来释放对象。从max_number_of_live_tokens队列开始。令牌限制可确保队列永远不会下溢或溢出。

整洁的部分是循环队列可以使用普通的串行代码实现。尾部/头部的数组和两个指针就足够了。不需要原子操作,锁定或内存栅栏。没有下溢/溢出的保证意味着可以通过碰撞尾指针(并且幸福地忽略头指针)来实现入队操作。反之亦然,对于deque操作。由于呼叫者是串行过滤器,因此不需要锁定。更糟糕的是,尾部和头部指针同时发生碰撞,但是是独立的。 TBB将负责内存防护。