Skip to content
  • 最新
  • 版块
  • 东岳流体
  • 随机看[请狂点我]
皮肤
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • 默认(不使用皮肤)
  • 不使用皮肤
折叠
CFD中文网

CFD中文网

  1. CFD中文网
  2. OpenFOAM
  3. 关于并行中的reduce函数

关于并行中的reduce函数

已定时 已固定 已锁定 已移动 OpenFOAM
6 帖子 2 发布者 4.0k 浏览
  • 从旧到新
  • 从新到旧
  • 最多赞同
回复
  • 在新帖中回复
登录后回复
此主题已被删除。只有拥有主题管理权限的用户可以查看。
  • T 离线
    T 离线
    Tens 神
    写于 最后由 Tens 编辑
    #1

    我在程序中定义了一个20个数的数组,在单核运行时结果看着没问题,并行运算时,就出错了,有人知道reduce函数是怎么实现的吗

    List<scalar> np(20,0.0);
    
    for (label i=0;i<20;i++)
    {
        np[i] += xxxx;   //每个时间步累加
        reduce(np[i], sumOp<scalar>());
    }
    
    T X 2 条回复 最后回复
  • T 离线
    T 离线
    Tens 神
    在 中回复了 Tens 最后由 编辑
    #2

    我猜测并行运算就是将变量拆分成数组,比如定义一个变量n,4核运算,就会生成一个数组n[4],数组的每个元素就在每个核内运算,然后reduce就是把数组求和,那对于本身就是一个数组的np[20],在reduce时就会出现问题?
    感觉把20个变量分别单独定义就能解决这个问题,但是这么多变量每个单独定义太麻烦了,有人有解决方法或者思路吗

    T 1 条回复 最后回复
  • T 离线
    T 离线
    Tens 神
    在 中回复了 Tens 最后由 编辑
    #3

    分别为单核和6核计算结果,因为时间步非常小,所以单核的变化很小是合理的,6核变化太大了
    583858f1-368a-4a0b-a35c-c1a873f4f188-image.png
    4dc27277-97cd-4a7b-9ee7-b62f23878fb3-image.png

    T 1 条回复 最后回复
  • T 离线
    T 离线
    Tens 神
    在 中回复了 Tens 最后由 编辑
    #4

    分别为单核和6核计算结果,因为时间步非常小,所以单核的变化很小是合理的,6核变化太大了

    这里弄错了,表格上的数据不是6核计算的结果,而是40核,忽然发现每一时间步的data都差不多是上一时间步的40倍,当改成6核运行时,又变成了6倍,是哪里的BUG造成的呢

    1 条回复 最后回复
  • X 离线
    X 离线
    xpqiu 超神
    在 中回复了 Tens 最后由 编辑
    #5

    @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 值越大。

    T 1 条回复 最后回复
  • T 离线
    T 离线
    Tens 神
    在 中回复了 xpqiu 最后由 编辑
    #6

    @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>());
    }
    
    1 条回复 最后回复

  • 登录

  • 登录或注册以进行搜索。
  • 第一个帖子
    最后一个帖子
0
  • 最新
  • 版块
  • 东岳流体
  • 随机看[请狂点我]