Load Balancing & Termination

因为并行程序的运行速度主要取决于最慢的那个进程。所以保证每个进程的运行时间差不多是非常重要的,这也是负载平衡。
并行计算中的任务调度

静态调度,动态调度和混合调度

静态调度(static scheduling):是指在并行程序编译时,就决定每个任务的执行处理器及其执行时序,它经常用于任务图比较确定的情况下。比如笔记中的Eratosthenes筛法的并行算法就是静态调度。它的缺点有:1. 未执行程序前,非常多的情况下很难估计准确的执行时间,2. 不同的情况下,通信开销变化非常大。3. 一些问题的执行步数非常难以确定,比如Manderbrot set
动态调度(dynamic scheduling):在并行程序运行过程中,根据当前任务调度及系统执行情况,临时决定每个任务的执行处理器及起始执行时刻。
混合调度(hybrid scheduling):是介于静态调度和动态调度两者之间的调度方法,它在编译时先静态调度部分任务,而剩余部分则采用动态调度方法在系统运行过程中来给他们分配处理器。
动态负载平衡策略分为集中式(Centralized ),全分布式(Totally Distributed)和半分布式。

集中式策略:由一个主控节点收集全局负载信息,其他节点将他们的状态信息传送给主控节点,并由主控节点做出决策。如上图所示,下面以Mandelbrot Set为例子,说明一下集中式的调度方法。

Mandelbrot集合

,如果
属于Mandelbrot集合

程序:

- 给一系列复数
- 求这一系列的复数当$|Z_{k}| > 2$时的迭代次数
- 迭代次数最大值取256
用640*480的图片显示

的Mandelbrot集合
表示为一个
的矩阵,以0进程为主进程,将480列做数据分解,按动态调度的方法分给其余各从进程。每当一个从进程完成该列的计算,便返回该列的列号和运算结果,然后主线程分配新的列让该进程计算。

对于图片每个点对应的复数c,返回的迭代次数的函数为

//C++
int cal_pixel (complex<float> c) {int count = 0; // number of iterationsint max= 256; // maximum iteration is 256complex<float> z{0,0}; // initialize complex number zdo {z=z*z+c;count++; // update iteration counter} while ((norm(z)< 4.0) && (count < max));return count;
}

动态调度的算法

主线程

当前正在计算的进程数为count = 0;
需要被发送的行号row = 0;
总进程数为num_proc,为这num_proc个进程分配前num_proc+1行的矩阵数据,每个进程一行。
此时count值为num_proc,row值为num_proc

do{//从从进程中得到计算结果recv(&slave, &r, color, PANY , result_tag);count--;//正在计算的进程数-1if (row < num_row) { // 矩阵的行还没分完send(row, Pslave , data_tag); //发送下一行count++;//正在计算的进程数+1row++;//下一个要分配的行号} else{//所有矩阵的行都处理完了send(row, Pslave , terminate_tag); //发送终止信号}display(r, color,picture); // 把计算结果保存到picture里面
} while(count > 0)

最后将picture写入硬盘。

从线程

对于从进程P(i)

recv(&row, Pmaster , source_tag);//从主进程中获得要计算的行号
while (source_tag == data_tag) { //得到的信号是要继续计算c.imag = min_imag + (row * scale_image);for (x=0; x<640; x++) {c.real = min_real + (x * scale_real);//矩阵行号和列号转化为复数ccolor[x] = cal_pixel (c); // 计算迭代次数}send(i, row, color, Pmaster , result_tag); // 发送结果到主进程recv(&row, Pmaster , source_tag);//从主进程得到新的行号或者终止信号
}

为了显示效果,我们将得到的图片取反,结果为

代码:https://github.com/chenlin0/Learning/tree/master/MPI/LoadingBalancing/
Mandelbrot_Set.cpp:源代码
Mandelbrot_Set:ubuntu下的可执行文件
Mandelbrot.txt:程序输出结果
Mandelbrot.png:输出结果取反后的图片

#include<iostream>
#include<complex>
#include"mpi.h"
#include<fstream>
using namespace std;
const int data_tag=0;
const int result_tag=1;
const int terminate_tag=2;
const int num_x=640;
const int num_y=480;
const float scale_x=1.0/160;
const float scale_y=1.0/160;
const complex<float> min_z={-2.0,-1.5};
struct Message{int id;int row;int color[num_x];
};
int main(int argc,char *argv[]){int cal_pixel (complex<float> c);int id;//进程编号int num_proc;//进程数int count; // 正在进行的进程int row; // 用来发送的矩阵行号int picture[num_y][num_x];MPI_Status stat;Message result;//传递结果complex<float> c;MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&id);MPI_Comm_size(MPI_COMM_WORLD,&num_proc);MPI_Datatype Messagetype;MPI_Datatype oldtype[2]={MPI_INT,MPI_INT};int blockcount[2]={2,num_x};MPI_Aint offset[2]={0,2*sizeof(int)};MPI_Type_struct(2,blockcount,offset,oldtype,&Messagetype);MPI_Type_commit(&Messagetype);if(!id){//主进程count = 0;row = 0;for (int i=1; i<num_proc; i++) { // 发送初始的行给各进程MPI_Send(&row,1,MPI_INT,i,data_tag,MPI_COMM_WORLD);count++;row++;}do{MPI_Recv(&result,1,Messagetype,MPI_ANY_SOURCE,result_tag,MPI_COMM_WORLD,&stat);//接受各进程的运算结果//  cout<<"Recv row:"<<result.row<<" id: "<<result.id<<" Tag:"<<stat.MPI_TAG<<endl;--count;//在计算的进程数-1for(int i=0;i<num_x;++i){//保存计算结果picture[result.row][i]=result.color[i];}if(row<num_y){//如果所有行没分配完MPI_Send(&row,1,MPI_INT,stat.MPI_SOURCE,data_tag,MPI_COMM_WORLD);//刚刚结束计算的进程stat.MPI_SOURCE分配新任务++count;//计算进程数+1++row;//分配下一个行}else{//所有的数据已经分配完MPI_Send(&row,1,MPI_INT,stat.MPI_SOURCE,terminate_tag,MPI_COMM_WORLD);//发送终止信号}}while(count>0);ofstream f1("Mandelbrot.txt",ios::out);//输出结果for(int i=0;i<num_y;++i){for(int j=0;j<num_x;++j){f1<<picture[i][j]<<" ";}f1<<endl;}f1.close();}else{MPI_Recv(&row,1,MPI_INT,0,MPI_ANY_TAG,MPI_COMM_WORLD,&stat);while(stat.MPI_TAG==data_tag){c.imag(min_z.imag()+row*scale_y);for(int i=0;i<num_x;++i){c.real(min_z.real()+i*scale_x);result.color[i]=cal_pixel(c);}//cout<<id<<":"<<endl;result.id=id;result.row=row;MPI_Send(&result,1,Messagetype,0,result_tag,MPI_COMM_WORLD);MPI_Recv(&row,1,MPI_INT,0,MPI_ANY_TAG,MPI_COMM_WORLD,&stat);}}MPI_Finalize();//结束MPI环境  return 0;
}
int cal_pixel (complex<float> c) {int count = 0; // number of iterationsint max= 256; // maximum iteration is 256complex<float> z{0,0}; // initialize complex number zdo {z=z*z+c;count++; // update iteration counter} while ((norm(z)< 4.0) && (count < max));return count;
}

P.S. 军训期间基本没啥时间写这个,不过军训快结束了。我回去整理一下笔记。调度策略可能还要写几次,然后还有并行排序的算法。接下来就是偏微分方程的数值解法,当然都需要是并行的。现在也在学着搞异构计算,看情况异构计算和偏微分方程组并行数值解法交叉更吧。写作的目的有二,一个是鞭策我自己努力学习新的并行计算笔记。二是觉得中文网站上的资料实在太少了。
不过写到偏微分方程并行求数值解,应该也没什么人看了,异构计算应该也没啥人看,纯属自娱自乐吧。

mpi并行 写同一文件_并行计算调度策略的笔记(001)相关推荐

  1. vivado常规操作之烧写bit文件_固化mcs文件_调试界面debug之ila与vio的操作

    目录 1 概述 2 烧写bit程序 3 Vivado 常用的调试界面 3.1 ila界面 3.1.1 添加需要查看的信号 3.1.2 添加条件触发信号 3.1.3 运行与停止ila界面,查看信号 3. ...

  2. java jxl 写 excel文件_使用jxl读和写Excel文件(速成)

    同行整理,简单明了,快速上手! =============================正文1============================ 最近和Excel频繁亲密接触,主要将N个Exc ...

  3. 写csv文件_机器学习Python实践——数据导入(CSV)

    一,CSV 逗号分隔值(逗号分隔值,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本).字幕:纯意味着该文件的英文一个字符序列,不含必须像二进制数 ...

  4. php写excel文件_使用PHPExcel读写excel

    PHPOffice出品的PHPExcel是PHP读取和生成Excel的极佳工具.本文参考官方文档,对PHPExcel进行简要总结,希望对使用PHPExcel操作Excel的同行有帮助. PHPExce ...

  5. python写xml文件_用python写xml文件

    def writeInfoToXml(filename, config_id, obj_name): from xml.dom.minidom import Document ''' eg: Web ...

  6. php写excel文件_利用PHPExcel实现Excel文件的写入和读取

    作为一个原本的Java党,用过PHP才知道,原来对于Excel文件的写入和读取原来可以这么简单! 利用PHP实现对于Excel的读取,主要借助于PHPExcel插件来完成. PHPExcel下载地址: ...

  7. java nio读取远程文件_操作分布式文件之七:如何并行读写远程文件

    FttpAdapter是通过FttpReadAdapter的tryReadAll方法进行并行读 FttpAdapter fa = new FttpAdapter("fttp://10.232 ...

  8. tinyxml 读取文本节点_【C++】【TinyXml】xml文件的读写功能使用——写xml文件

    TinyXml工具是常用比较简单的C++中xml读写的工具 需要加载 #include "TinyXml\tinyxml.h" 在TinyXML中,根据XML的各种元素来定义了一些 ...

  9. python创建nc文件_如何python写nc文件

    今天试了一下用PyNIO写nc文件,难用的一腿 算了,还是用netcdf模块写了. 代码如下: # -*- coding: utf-8 -*- import numpy as np import sy ...

最新文章

  1. qt 单元格加上边框_Excel如何自动添加边框?学会这个方法效率加倍!
  2. 黄聪:C# webBrowser控件禁用alert,confirm之类的弹窗解决方案
  3. ps光效插件_全套光效PS插件(2019),只有你想不到的,没有它做不到的PS特效...
  4. 华为开源自研AI框架MindSpore!自动微分、并行加持,一次训练,可多场景部署...
  5. 微信小程序AES加密解密
  6. python就业方向及工资-Python的5大就业方向,薪资诱人前景好!
  7. go中 -strconv包的使用
  8. 可编辑树Ztree的使用(包括对后台数据库的增删改查)
  9. 使用jQuery的hover事件在IE中不停闪动的解决方法
  10. 外部定义了一个数组,在函数内用指针对其操作
  11. 日常问题——初始化Hive仓库报错com.google.common.base.Preconditions.checkArgument
  12. 让我们一起Go(九)
  13. redis与memcached区别
  14. 操作系统概念学习笔记 10 CPU调度
  15. springcloud 心得记录
  16. 0xc0000001报错解决办法
  17. 2023年最新微信记账小程序源码+简约大气
  18. RW文档翻译学习——RW-BT-SW-COMMON-FS
  19. 洛谷4234最小差值生成树 (LCT维护生成树)
  20. 天耀18期 - 11.封装类及常用类【作业】

热门文章

  1. 常见数据分析误区有哪些
  2. qt串口通信_Qt编写气体安全管理系统29-跨平台
  3. 玩转CSS盒子之 三角形盒子
  4. Python容器专题 - deque(队列)--双向队列对象
  5. https 加端口_Ubuntu 安装Node 10.16 跑 Nodeppt 加Hexo博客再来个为知笔记私有云
  6. php cmd 命令行参数,php获取命令行参数
  7. P1629 邮递员送信(正反向建图 or 暴力)
  8. python代码解读器_python文章生成器(附源码+讲解)
  9. [人脸识别]什么叫One-shot learning
  10. Rational Rose 逆向工程(java) 常见问题二则