2

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

4

1 回答 1

3

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

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

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

于 2013-03-01T22:19:03.753 回答