C++ 理解tbb::parallel_reduce的并发性
我使用的命令式形式是C++ 理解tbb::parallel_reduce的并发性,c++,concurrency,tbb,C++,Concurrency,Tbb,我使用的命令式形式是tbb::parallel\u reduce(range,body)as。医生说: 并行_reduce使用拆分构造函数为每个线程创建一个或多个主体副本。它可以在主体的运算符()或方法join同时运行时复制主体。您有责任确保此类并发的安全性 所以我知道Body::Body(Body&,split)可以作为Body::operator()或Body::join(Body&rhs)do运行 我的问题是: 1) Body::operator()和Body::join(Body&rhs
tbb::parallel\u reduce(range,body)
as。医生说:
并行_reduce使用拆分构造函数为每个线程创建一个或多个主体副本。它可以在主体的运算符()或方法join同时运行时复制主体。您有责任确保此类并发的安全性
所以我知道Body::Body(Body&,split)
可以作为Body::operator()
或Body::join(Body&rhs)
do运行
我的问题是:
1) Body::operator()
和Body::join(Body&rhs)
可以同时运行吗
2) 能否安全地修改rhs
W.r.t.1),我相信只有在完成operator()
之后才能调用join
。另外,看看Intel文档中的示例,很明显他们可以修改相同的数据,而不会出现数据争用问题:
struct Sum {
float value;
...
void operator()( const blocked_range<float*>& r ) {
value = ...;
}
void join( Sum& rhs ) {value += rhs.value;}
};
struct Sum{
浮动值;
...
void运算符()(常数阻塞的\u范围和r){
值=。。。;
}
void join(Sum&rhs){value+=rhs.value;}
};
关于并发调用方法涉及哪些实例的文档不够清楚。但它暗示:
在典型使用中,安全无需额外努力
同一实例没有并发性。因此,像在串行代码中一样拆分或连接两个实例是安全的<代码>运算符()也不能在同一实例上同时调用。因此,文档必须真正说明:
当主体的操作符()或方法join在不同实例上并发运行时,它可能会复制主体
顺便说一句,报价
并行_reduce递归地将范围拆分为子范围,直到每个子范围的_divisible()为false`
仅对
simple\u partitioner
是正确的,对于其他分区器,它可以在到达is\u divisible()==false
之前停止拆分。对于并发调用方法涉及的实例,文档不够清楚。但它暗示:
在典型使用中,安全无需额外努力
同一实例没有并发性。因此,像在串行代码中一样拆分或连接两个实例是安全的<代码>运算符()也不能在同一实例上同时调用。因此,文档必须真正说明:
当主体的操作符()或方法join在不同实例上并发运行时,它可能会复制主体
顺便说一句,报价
并行_reduce递归地将范围拆分为子范围,直到每个子范围的_divisible()为false`
仅对
simple\u partitioner
是正确的,对于其他分区器,它可以在达到is\u divisible()==false
之前停止拆分tbb::parallel\u reduce使用的Body
对象的生存期为:
它由拆分构造函数创建为另一个Body对象的“右”侧,然后更新为仅处理“左”侧
其运算符()
应用于一个或多个后续范围
它可以用作拆分新实体的构造函数的参数(是的,不止一次),并根据上面的#1进行更新
它的方法join()
是为#3中从中拆分的每个对象调用的
它作为rhs
连接回从中拆分的实体对象
加入后会被销毁
在上述操作中,#3可以同时运行到#2和#4;其余的都是顺序的,即使不一定由单个线程调用。换句话说,当一个实体为某些子范围积累部分缩减或连接另一个实体的结果时,它可以通过拆分新实体的构造函数来更新。这是可能需要保护的地方,但通常这些调用访问身体的不同部分
因此,您的问题的答案是:
1) Body::operator()
和Body::join(Body&rhs)
可以同时运行吗
否。join()
仅在对operator()
的所有调用之后才被调用,无论是对于this
还是rhs
2) 能否安全地修改rhs
是的,它可以。但是,除了可能在连接过程中移动其内容并相应地更新状态外,修改rhs
没有什么意义,因为它将在join()
调用之后立即被销毁。tbb::parallel\u reduce使用的主体
对象的生存期是:
它由拆分构造函数创建为另一个Body对象的“右”侧,然后更新为仅处理“左”侧
其运算符()
应用于一个或多个后续范围
它可以用作拆分新实体的构造函数的参数(是的,不止一次),并根据上面的#1进行更新
它的方法join()
是为#3中从中拆分的每个对象调用的
它作为rhs
连接回从中拆分的实体对象
加入后会被销毁
在上述操作中,#3可以同时运行到#2和#4;其余的都是顺序的,即使不一定由单个线程调用。换句话说,当一个实体为某些子范围积累部分缩减或连接另一个实体的结果时,它可以通过拆分新实体的构造函数来更新。这是可能需要保护的地方,但通常这些调用访问身体的不同部分
因此,您的问题的答案是:
1) Body::operator()
和Body::join(Body&rhs)
可以同时运行吗
否。join()
仅在所有ca之后调用