浅谈UDF并行
首先我们来看说明UDF并行流程的这个图
网格和求解数据分布和储存在计算节点(compute-node)处理器上,而对于GUI界面和主机(host)节点上不存储任何数据,主机节点将命令从GUI传递到0节点(Compute-Node-0),然后0节点(Compute-Node-0)再将命令传递给其他计算节点(比如图中的Compute-Node-1,Compute-Node-2,Compute-Node-3),其他节点的数据想要汇总到主机节点显示在GUI上,也需要其他各个计算节点将计算数据汇总给0节点(Compute-Node-0),然后0节点(Compute-Node-0)将自身的数据和其他计算节点的数据(比如图中的Compute-Node-1,Compute-Node-2,Compute-Node-3)汇总起来,发送给主机(host)节点
我们可以将计算理解为一个班级,其中班主任就是主机节点(host),班长就是0节点(Compute-Node-0),其他计算节点(比如图中的Compute-Node-1,Compute-Node-2,Compute-Node-3)就是普通学生。
所谓闻道有先后,术业有专攻。班主任(host)应该做班主任的事情,班长(Compute-Node-0)和其他同学(图中的Compute-Node-1,Compute-Node-2,Compute-Node-3)也应该去做自己的事情。那么如何区分班主任(host)和班长(Compute-Node-0)以及其他同学(图中的Compute-Node-1,Compute-Node-2,Compute-Node-3)呢?这个时候区分班主任(host)和班长(Compute-Node-0)以及其他同学(图中的Compute-Node-1,Compute-Node-2,Compute-Node-3)的标识符就应该登场了。
对于班主任(host)的命令,我们用如下的标识符进行界定:
在标识符之间的代码就是班主任(host)做的事情
对于所有学生(Compute-Node-0,Compute-Node-1,Compute-Node-2,Compute-Node-3),我们采用如下的标识符进行界定:
在标识符之间的代码就是所有学生(Compute-Node-0,Compute-Node-1,Compute-Node-2,Compute-Node-3)做的事情。
注1:班长(Compute-Node-0)也是学生,所以是同一个标识符。后面我们会讲到如何区分班长(Compute-Node-0)和普通学生(图中的Compute-Node-1,Compute-Node-2,Compute-Node-3)。
注2:针对于c语言前面加英文的叹号(!)表示取反的意思,所以就有了如下代码:
表示除主机(host)以外的其他节点,其实就是指计算节点 (Compute-Node-0,Compute-Node-1,Compute-Node-2,Compute-Node-3)
表示除了计算节点以外的(Compute-Node-0,Compute-Node-1,Compute-Node-2,Compute-Node-3),其实就是指主机节点(host)
其他的区分宏可见《ANSYS Fluent Customization Manual》,如下图:
我们可以稍微修改Fluent 2019 R1《ANSYS Fluent Customization Manual》507页上的一段简单代码来验证上面的说法:
启动Fluent,我们这里选择5核并行
编译上面这段代码,然后加载,运行结果如下:
我们按照串行(Serial)的思路再改写一下上面的代码,不加标识符,看看会有什么结果
重复上面的步骤启动Fluent,编译,我们看到编译是没有报错的,然后加载,运行结果如下:
我们可以看到如果我们不加标识符的话,完全就乱套了,人人都在高吼自己是班主任(host),这个结果当然是不正确的,也不是我们想要的。所以有时候我们在使用Fluent输出边界面积的时候会出现面积为零的情况,如下:
这就是代码没有串行化,主机节点(host)和部分计算节点(Compute-Node)没有存储对应边界的数据,从而返回面积为零,并且没有标识符,程序乱套了。
班主任和同学之间如何交流呢?班主任(host)小事(比如边界上的平均压力,平均速度,质量流量,体积流量等)会直接向所有的同学(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)宣布事情,同学们(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)也会将一些意见(比如边界上的平均压力,平均速度,质量流量,体积流量等)汇总以后将直接告诉班主任(host)。但是有时候同学们(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)的意见太多,直接告诉班主任(host)不方便,这个时候就需要班长(Compute-Node-0)出面,将所有同学(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)的意见全部汇总到自己这里,然后班长(Compute-Node-0)再将汇总以后的意见反馈给班主任(host)
班主任(host)直接向所有同学(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)宣布事情用:
host_to_node_type_num(val_1,val_2,...,val_num)
注:上面的函数中,
单词type是传递数据的类型比如int,double,float,real,char等等
单词num是传递变量的数量,那么就是1,2,3,4…
同学们(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)将意见汇总以后将直接告诉班主任(host)用:
node_to_host_type_num(val_1,val_2,...,val_num)
注:上面的函数中,
单词type是传递数据的类型比如int,double,float,real,char等等
单词num是传递变量的数量,那么就是1,2,3,4…
在使用上面这个函数以前,需要先调用前缀为PRF_宏进行汇总
一段并行求解壁面平均压力的示例代码如下:
下面一个简单的例子来说明串行代码如何并行化
示例网格下载链接: https://pan.baidu.com/s/1mWdtvtSKjFb-0L7-sAVb4g
提取码: x5hv
这是一段求解出口处面积的串行代码:
串行的执行结果:
我们将这段串行代码并行化:
并行代码执行的结果:
但当我们意见比较多(数据量比较大,比如将所有网格的坐标输出)的时候,我们就需要先将班长(Compute-Node-0)以外的所有同学(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)的意见(数据)汇总到班长(Compute-Node-0)处,然后班长(Compute-Node-0)再将所有的意见(数据)转发给班主任(host)
同学们(Compute-Node-0, Compute-Node-1,Compute-Node-2,Compute-Node-3)向班长(host)汇总一般如下编写: