关于并行中的reduce函数
-
@Tens 在 关于并行中的reduce函数 中说:
List<scalar> np(20,0.0); for (label i=0;i<20;i++) { np[i] += xxxx; //每个时间步累加 reduce(np[i], sumOp<scalar>()); }
这段代码如果以比如 6 核运行,那么如果先不看 reduce 这句,则是这6个核各自都会创建一个长度为 20 的list,然后执行这个循环,最终得到的结果是每个核各自有一份自己的 np 值,如果xxxx是常数,则每个核的np值都一样,如果xxxx是一个不同核数取值不一样的数,则每个核中最终得到的 np 值不一样。
reduce(np[i], sumOp<scalar>()) 的作用是将每个核的 np[i] 全都累加起来(因为这里的第二个参数是sumOp,表示加和),然后将累加之后得到的值再分发给所有核,最终每个核中的 np 的值都一样。
所以加上reduce之后导致的结果就是,最终得到的每个核中的 np的值都一样,但是 np 的值显然会受核数影响。
举例说,假设 xxxx 是常数,等于10 ,则 单核运行时,np 的每个分量都是10,如果6核运行,则最终得到np 的每个分量都是 60。因为reduce之前,每个核的 np 都是10,reduce 的时候,将每个核的值累加起来,得到60。以此类推,核数越多,得到的 np 值越大。
-
@xpqiu 好像是这样的,但是xxxx是对颗粒的某个值进行统计,类似于求D32。xxxx应该是不同核内取值不一样的数,如果这样的话,那么每个核内是计算自身负责区域内的颗粒,redece则是求和,应该是没问题的
下面是of内求D32的代码:template<class CloudType> inline Foam::scalar Foam::KinematicCloud<CloudType>::Dij ( const label i, const label j ) const { scalar si = 0.0; scalar sj = 0.0; forAllConstIter(typename KinematicCloud<CloudType>, *this, iter) { const parcelType& p = iter(); si += p.nParticle()*pow(p.d(), i); sj += p.nParticle()*pow(p.d(), j); } reduce(si, sumOp<scalar>()); reduce(sj, sumOp<scalar>()); sj = max(sj, vSmall); return si/sj; }
我的代码是仿照写的,不过我要统计的是20个变量,所以直接定义List:
List<scalar> np(20,0.0); for (label i=0;i<20;i++) { forAllIter(typename basicSprayCloud::sprayCloudType,parcels,pIter) { parceltype& p = pIter(); if (p满足条件) { np[i] += xxxx; //每个时间步累加 } } reduce(np[i], sumOp<scalar>()); }