Tbb并行管道就地修改令牌

Tbb parallel pipeline inplace modification of tokens

本文关键字:修改 令牌 并行 管道 Tbb      更新时间:2023-10-16

我想使用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将在输入和输出过滤器中被分配和释放

是的,允许对传递给过滤器的对象进行就地修改,并且在处理复制成本较高的对象时通常很有用。当我用parallel_pipeline并行化Bzip2时,我已经这样做了。就TBB而言,示例中的指针"input"只是一个TBB不试图解释的值。

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

巧妙之处在于,循环队列可以使用简单的串行代码来实现。一个数组和两个指向尾部/头部的指针就足够了。不需要原子操作、锁定或内存隔离。没有底流/溢出的保证意味着可以通过碰撞尾指针来实现队列操作(并完全忽略头指针)。deque操作反之亦然。不需要锁定,因为调用者是串行过滤器。最坏的情况是,尾部指针和头指针同时碰撞,但彼此独立。TBB将负责内存隔离。