其他分享
首页 > 其他分享> > 并行与分布式计算复习要点

并行与分布式计算复习要点

作者:互联网

概念

计算机架构

image

SISD

SIMD

MISD

MIMD

共享内存

并行计算机的一种存储结构,有全局地址空间

根据内存访问时间被归为UMA、NUMA

UMA 统一内存访问

NUMA 非统一内存访问

分布式内存

并行计算机的一种存储结构

并行计算模型

PRAM

APRAM

BSP

并行方法的一般设计过程PCAM

MPI并行编程

并行测试标准

通信测试标准

image

Amdahl定律(固定负载)

image
image

Gustafson定律

实际问题中固定负载量而增加处理机数目没有意义,因此增多处理机,必须也增多负载
image
image

加速比与效率

效率=S/P
加速比/处理机数
问题规模不变,处理机数量增加,效率就下降

⭐⭐消息传递三种方式

进程之间通过消息传递实现数据共享和进程同步

三种方式异同

image
image
image
image

MPI点对点通信与集群通信

点对点通信

image
Q接收的是下一次用来计算的X
Q发送的是上一次计算完的Y
接着用这次收到的X计算Y
下图的代码应该是进程流水线具体是怎么接收发送的,需要双缓冲
image
Isend, Irevc是非阻塞式,调用完立刻返回,需要调用等待函数
X Y Xbuf0 Xbuf1 Ybuf0 Ybuf1 Xin Yout都是指针
Xin Yout是要发送或接收的数据的指针
X Y指当前计算用的缓冲区

集群通信

image
通信子中的所有进程都必须调用群集例程

MPI_Scatter(SendAddress, SendCount, SendDateTyoe, RecvAddress, RecvCount, RecvDataType, Root, Comm);
MPI_Gather(SendAddress, SendCount, SendDateTyoe, RecvAddress, RecvCount, RecvDataType, Root, Comm);

播撒:root进程给每个进程都发送一个不同的消息,要发送的消息有序的存放在root进程的发送缓存中
聚集:root从每个进程接收消息,接收的消息有序的存放在root进程的接收缓存中。
播撒和聚集是两个相反的操作
image

MPI_Allgather(SendAddress, SendCount, SendDateTyoe, RecvAddress, RecvCount, RecvDataType, Comm);

image

MPI_Alltoall(SendAddress, SendCount, SendDateTyoe, RecvAddress, RecvCount, RecvDataType, Comm);

每个进程都向n个进程发送消息,要发送的消息有序的存放在发送缓存中
换个角度,每个进程都从n个进程接收消息,要接收的消息有序的存放在接收缓存中
全局交换就是n个进程做n次gather,一次全局交换有n^2个消息通信
image

MPI_Reduce(SendAddress, RecvAddress, Count, DataType, Op, Root, Comm);

扫描:没有了root,将部分值组合成n个最终值,存放在每个进程的RecvAddress中,操作为op

MPI_Scan(SendAddress, RecvAddress, Count, DataType, Op, Comm);
MPI_Barrier(Comm);

通信子中所有进程进行同步,即相互等待,直到所有进程执行完自己的Barrier函数

⭐⭐MPI求PI的值

#include <stdio.h>
#include <mpi.h>
#include <math.h>
long    n,    	/*number of slices         */
        i;    	/* slice counter           */
double sum, 	/* running sum             */
        pi,     /* approximate value of pi */
        mypi,
        x,      /* independent var.        */
        h;      /* base of slice           */
int group_size,my_rank;
 
main(argc,argv)
int argc;
char* argv[]; 
{      
	int group_size,my_rank;
	MPI_Status status;
	MPI_Init(&argc,&argv);
	MPI_Comm_rank( MPI_COMM_WORLD, &my_rank);
	MPI_Comm_size( MPI_COMM_WORLD, &group_size);
	 
	n=2000;
	/* Broadcast n to all other nodes */
	MPI_Bcast(&n,1,MPI_LONG,0,MPI_COMM_WORLD); 
	h = 1.0/(double) n;
	sum = 0.0;
	//每个进程计算一部分
	for (i = my_rank; i < n; i += group_size) {
		x = h*(i+0.5);
		sum = sum +4.0/(1.0+x*x);
	}
	mypi = h*sum;
	/*Global sum * reduce到root进程,用的是求和运算*/ 
	MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD); 
	if(my_rank==0) {        /* Node 0 handles output */
	printf("pi is approximately : %.16lf\n",pi);
	}
	MPI_Finalize();
}

MapReduce

模型原理

对于相互之间不存在依赖关系的大数据,实现并行的最佳方法就是分而治之。
MPI等并行方法缺少高层并行编程模型,程序员需要自行指定存储、划分、计算等任务;缺乏统一的并行框架结构,程序员需要考虑诸多细节。
因此,MapReduce设计并提供了统一的计算框架,为程序员隐藏了大多数系统层的细节,用Map和Reduce两个函数提供了高层并发编程模型抽象。
image
一个大的数据集被分成许多独立的分片(split),这些分片给多个Map任务并行处理
<k1, v1>:k1是主键,v1是数据,经Map处理后生成了很多中间结果,即List(<k2,v2>。
Reduce对中间结果进行合并,把key值相等的数据合并在一起,即<k2, List(v2)>,最后生成最终结果,即<k3, v3>

⭐⭐wordcount实例

图示:
image
核心伪代码:
image

大概的伪代码点击查看
public class Mapper()
{
	/*
	key和value是输入的键值对
	context是输出的结果
	*/
	public void map(Object key, Text value, Context context)
				throws IOException, InterruptedException {
		//默认取每行的数据,每行都有空格,按空格切分
		String lineContent = value.toString();	//取出每行的数据
		String words[] = lineContent.split(" ");	//进行每行数据的拆分
		
		for(String word : words){	//循环每个单词而后进行数据的生成
				//每一个单词最终生成的保存个数是1
				context.write(word, 1);
		}
	}	
}

public class Reducer()
{
	/*
	key和values是map输出的中间结果,需要reduce处理
	context是reducer输出的最终结果
	*/	
	public void reduce(Text key, Iterable<IntWritable> values, Context context)
			throws IOException, InterruptedException {{
		int sum = 0 ;	//保存每个单词出现的总次数
	}
	for(IntWritable count :  values){
		sum += count.get();
	}
	context.write(key, sum);
}

public static void main(String[] args) throws Exception{
	//进行相关配置
	Configuration configuration=new Configuration();
	//创建一个工作对象
	Job job=Job.getInstance(configuration);
	//设置当前的工作对象
	job.setJarByClass(Myjob.class);
	//设置map对象类
	job.setMapperClass(Mapper.class);
	//设置reduce对象类
	job.setReducerClass(Reducer.class);
	//设置输出的key类型
	job.setOutputKeyClass(Text.class);
	//设置输出的value类型
	job.setOutputValueClass(IntWritable.class);
	//设置输入的文件位置
	FileInputFormat.addInputPath(job, new Path("/hadoop/hadoop.txt"));
	//设置输出的文件位置
	FileOutputFormat.setOutputPath(job, new Path("/hadoop/out"));
	job.waitForCompletion(true);
	return 0;
}

容错控制策略(4种)

容错:系统能在发生故障的前提下继续提供服务

检查点容错

过程:周期性备份和回滚恢复
任务出错时,可以从最近一次成功的checkpoint处恢复计算
image
备份开销和恢复效率不可兼得

血统容错

输入输出的依赖关系:
窄依赖:一对一
宽依赖:一对多
image
血统容错:记录中间结果的依赖关系,根据血统信息来重新计算一部分,恢复丢失的数据
如果血统信息过长,计算就会比较耗时,也需要使用检查点,避免太多的重复计算

推测式执行

如果有一个task执行的太慢,就会启动一个备份任务,最终使用原任务和备份任务中执行较快的task的结果。
推测式执行默认是关闭的,因为重复的任务会使集群的效率降低。
推测式执行是以空间换时间,一般在资源空闲且作业完成度较大时启动

补偿式容错

不做准备,出现故障时重置丢失数据(重新计算)
image

注: 有错误请指出!

标签:复习,并行,分布式计算,MPI,发送,处理器,进程,接收,内存
来源: https://www.cnblogs.com/Hfolsvh/p/15756545.html