我使用tbb::parallel_reduce(range,body)
作为documented here的命令形式。医生说:
parallel_reduce使用拆分构造函数为每个线程创建一个或多个正文副本。当body的operator()或方法join同时运行时,它可以复制一个body。您有责任确保此类并发的安全性。
因此,我了解Body::Body( Body&, split )
可以Body::operator()
或Body::join( Body& rhs )
运行。
我的问题是:
1)Body::operator()
和Body::join( Body& rhs )
可以同时运行吗?
2)Body::join( Body& rhs )
可以安全地修改rhs
吗?
W.r.t。 1),我相信只有在join
完成后才能调用operator()
。另外,看一下英特尔文档中的示例,很明显他们可以在没有数据竞争问题的情况下修改相同的数据:
struct Sum {
float value;
...
void operator()( const blocked_range<float*>& r ) {
value = ...;
}
void join( Sum& rhs ) {value += rhs.value;}
};
答案 0 :(得分:2)
Body
使用的tbb::parallel_reduce
对象的生命周期为:
operator()
适用于一个或多个后续范围。join()
。rhs
加入到它被拆分的正文对象中。在上述操作中,#3可以同时运行到#2和#4;所有其余的都是顺序的,即使不一定由单个线程调用。换句话说,当一个体积累了一些子范围的部分缩减或者从另一个体连接结果时,可以通过拆分新体的构造函数来更新它。这可能是必要的保护,但通常这些调用访问身体的不同部分。
所以,你的问题的答案是:
1)
Body::operator()
和Body::join( Body& rhs )
可以同时运行吗?
没有。仅在join()
和operator()
的所有this
来电之后调用rhs
。
2)
Body::join( Body& rhs )
可以安全地修改rhs
吗?
是的,它可以。但除了可能在连接期间移动其内容并相应地更新状态之外,修改rhs
没有多大意义,因为它会在join()
调用之后立即销毁。
答案 1 :(得分:1)
有关并发调用方法所涉及的实例的文档不够清楚。但它提示:
在典型的使用中,安全性不需要额外的努力。
同一个实例没有并发性。因此,像在串行代码中一样拆分或连接两个实例是安全的。 operator()
也不能在同一个实例上同时调用。所以文档必须说:
当body的operator()或方法join在不同的实例上同时运行时,它可以复制一个body。
BTW,引用
parallel_reduce递归地将范围拆分为该点的子范围,使得每个子范围的is_divisible()为false。
仅适用于simple_partitioner
,对于其他分区,它可以在到达is_divisible() == false
之前停止分割