MPI_Init(&argc, &argv)
MPI_Finalize()
一个通信域,包含通信的所有进程
MPI_Comm_rank(MPI_COMM_WORLD, &node);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Send(message, strlen(message), MPI_CHAR, 1, 99, MPI_COMM_WORLD);
1是目的进程标识
MPI_Recv(message, strlen(message), MPI_CHAR, 0, 99, MPI_COMM_WORLD);
0是发送进程标识
#include"mpi.h"
int main(int argc, char **argv){
char message[20];
int myrank;
MPI_Init(&argc,&argv); // 要传地址
MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
if(myrank == 0){
strcy(message,"Hello, process 1");
MPI_Send(message, strlen(message), MPI_CHAR, 1, 99, MPI_COMM_WORLD);
}
else if(myrank == 1){
MPI_Recv(message, strlen(message), MPI_CHAR, 0, 99, MPI_COMM_WORLD);
printf("messge: %s",message);
}
MPI_Finalize();
}
master(0或者最后一个)进程退出,其他进程堵塞
#include"mpi.h"
#include
int main(int argc, char **argv){
int node, size,i;
int masternode = 0;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&node);
MPI_Comm_size(MPI_COMM_WORLD,&size);
for(i=1;i<argc;++i){
fprintf(stderr,"myid=%d, procs=%d, argv[%d]=%s\n",node,size,i,argv[i]);
if(argv[i]&&strcmp("lastmaster",argv[i])==0){//字符串相等
masternode=size-1;
}
}
if(node == masternode){
fprintf(stderr,"myid=%d is masternode Abort!\n",node);
MPI_Abort(MPI_COMM_WORLD,99);
}
else{
fprintf(stderr,"myid=%d is not masternode Barrier!\n",node);
MPI_Barrier(MPI_COMM_WORLD);
}
MPI_Finalize();
}
#include"mpi.h"
#include
int main(int argc, char **argv){
int rank, size, value;
MPI_Status status;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
do{
if(rank==0){
fprintf(stderr,"\nPlease give new value=");
scanf("%d",&value);
fprintf(stderr,"%d read <-<- (%d)\n",rank,value);
if(size>1){//进程数大于1
MPI_Send(&value,1,MPI_INT,rank+1,0,MPI_COMM_WORLD);
fprintf(stderr,"%d send (%d) ->-> %d\n",rank,value,rank+1);
}
}
else{
MPI_Recv(&value, 1, MPI_INT, rank-1,0, MPI_COMM_WORLD,&status);
fprintf(stderr,"%d receive(%d) <-<- %d\n",rank,value,rank-1);
if(rank<size-1){
MPI_Send(&value,1,MPI_INT,rank+1,0,MPI_COMM_WORLD);
fprintf(stderr,"%d send (%d)->-> %d\n",rank,value,rank+1);
}
}
MPI_Barrier(MPI_COMM_WORLD);//执行一下同步,让所有进程执行完,使前后两次输入数据分隔开
}while(value>=0);
MPI_Finalize();
}
#include"mpi.h"
#include
#include
void Hello(void);
int main(int argc, char **argv){
int rank, option, namelen, size;
char processor_name[MPI_MAX_PROCESSOR_NAME];
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(size<2){
fprintf(stderr,"systest requires at least 2 processes");
MPI_Abort(MPI_COMM_WORLD,1);
}
MPI_Get_processor_name(processor_name,&namelen);
fpritnf(stderr,"Process %d is alive on %s\n",rank,processor_name);
MPI_Barrier(MPI_COMM_WORLD);
Hello();
MPI_Finalize();
}
void Hello(void){
int size, rank;
int type = 1;
int buffer[2], node;
MPI_Status status;
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(rank==0){ //0进程负责打印提示消息
printf("\nHello test from all to all\n");
fflush(stdout);
}
for(node=0; node<size; node++){
if(node!=rank){
buffer[0]=rank;//自身标识
buffer[1]=node;//被问候标识
MPI_Send(buffer,2,MPI_INT,node,type,MPI_COMM_WORLD);
MPI_Recv(buffer,2,MPI_INT,node,type,MPI_COMM_WORLD,&status);
if((buffer[0]!=rank)||(buffer[1]!=node)){
//不是问候自己的或者不是不是以被问候的身份问候自己
(void) fprintf(stderr, "Hello: %d!=%d or %d!=%d\n",buffer[0],node,buffer[1],rank);
printf("Mismatch on hello process ids; node = %d\n",node);
}
printf("Hello form %d to %d\n",rank,node);
fflush(stdout);
}
}
}
#include"mpi.h"
#include
int main(int argc, char **argv){
int rank, size, buff[1];
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(rank==0){
for(int i=0;i<100*(size-1);++i){
MPI_Recv(buf,1,MPI_INT,MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_COMM_WORLD,&status);
printf("Msg=%d from %d with tag%d\n",buf[0],status.MPI_SOURCE,status.MPI_TAG);
}
}
else{
for(int i=0;i<100;++i){
buf[0]=rank+i;
MPI_Send(buf,1,MPI_INT,0,i,MPI_COMM_WORLD);
}
}
MPI_Finalize();
}
通信模式 | 发送 | 接收 |
---|---|---|
标准通信 | MPI_Send | MPI_Recv |
缓存通信 | MPI_Bsend | |
同步通信 | MPI_Ssend | |
就绪通信 | MPI_Rsend |
使用同步消息发送,发送进程分别以同步方式发送1个和4个数据,消息标识tag分别为1和2,接收进程用标准接收操作接收,并检查收到数据的个数
#include"mpi.h"
#include
#define SIZE 10
static int src = 0, dest = 1;//源进程,目的进程
int main(int argc, char **argv){
int rank,size;
int flag,rval,i;
int act_size = 0;
int buffer[SIZE];
MPI_STATUS status, status1, status2;
int count1, count2;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(size!=2){
fprintf(stderr,"*** This program uses exactly 2 processes! ***\n");
MPI_Abort(MPI_COMM_WORLD,1);
}
act_size = 5; // 最大消息长度
if(rank == src){ // 当前进程为发送进程
act_size = 1;
MPI_Ssend(buffer, act_size, MPI_INT, dest, 1, MPI_COMM_WORLD);
fprintf(stderr,"MPI_Ssend %d data, tag = 1\n",act_size);
act_size = 4;
MPI_Ssend(buffer, act_size, MPI_INT, dest, 2, MPI_COMM_WORLD);
fprintf(stderr,"MPI_Ssend %d data, tag = 2\n",act_size);
}
else if(rank == dest){
MPI_Recv(buffer, act_size, MPI_INT, src, 1, MPI_COMM_WORLD, &status1);
MPI_Recv(buffer, act_size, MPI_INT, src, 2, MPI_COMM_WORLD, &status2);
// act_size 是最大消息长度
MPI_Get_count(&status1, MPI_INT, &count1);
fprintf(stderr,"receive %d data, tag = %d\n",count1,status1.MPI_TAG);
MPI_Get_count(&status2, MPI_INT, &count2);
fprintf(stderr,"receive %d data, tag = %d\n",count2,status2.MPI_TAG);
}
MPI_Finalize();
}
MPI_Bcast(&value, 1, MPI_INT, 0, MPI_COMM_WORLD);
#include
#include"mpi.h"
int main(int argc, char **argv){
int rank, value;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
do{
if(rank==0){
scanf("%d",&value);
}
MPI_Bcast(&value,1,MPI_INT,0,MPI_COMM_WORLD);
//如果当前是广播进程就发送,如果不是就接收,根据进程标识Bcast自动处理
printf("Process %d got %d\n",rank,value);
}while(value>=0); // 所有进程共用value
MPI_Finalize();
}
MPI_Gather(sendarray,100,MPI_INT,rbuf,rcounts,displs,MPI_INT,root,MPI_COMM_WORLD);
// rbuf 整型数组,接收消息缓存区起始地址
// rcounts 整型数组,每个进程接收的数据个数
// displs 整型数组,每个入口相对于rbuf的偏移
// root 接收进程的标识号
注意为数组开辟空间
收集和散发都是对应位置的缓存区数据交流
MPI_Scatter(sendarray,100,MPI_INT,rbuf,100,MPI_INT,root,MPI_COMM_WORLD);
// root 发送进程的标识号
MPI_Allgather(sendarray,100,MPI_INT,rbuf,100,MPI_INT,MPI_COMM_WORLD);
使程序并行化
double area, pi,x;
int i, n;
area = 0.0;
#program omp parallel for private(x)
for (i = 0; i < n; ++i){
x = (i+0.5)/n;
#pragma omp critical // 生成一个代码临界区,使执行该段代码的线程互斥
area += 4.0/(1.0 + x*x);
}
pi = area / n;
归约操作
//归约操作
// 负责将部分和存储到私有变量中并在循环结束时将各个部分和相加等具体的操作
reduction(<op>:<variable>)
area = 0.0;
#pragma opm parallel for private(x) reduction(+:area)
for(i=0;i<n;++i){
x = (i+0.5)/n;
area += 4.0 / (1.0 + x*x);
}
pi = area / n;
并行计算是相对于串行计算来说的,可分为时间上的并行和空间上的并行。时间上的并行指的就是流水线技术,而空间上的并行则是指用多个处理器并发的执行计算。并行计算的目的就是提供单处理器无法提供的性能,使用多处理器求解单个问题。
分布式计算研究如何把一个需要非常巨大的计算能力才能解决的问题分成许多小的部分,然后把这些部分分配个许多计算机进行处理,最后把这些计算结果综合起来得到最终的结果。
并行计算机即能在同一时间执行多条指令或处理多个数据的计算机,并行计算机是并行计算的物理载体。
Hadoop是Apache软件基金会旗下的一个开源分布式计算平台,为用户提供了系统底层细节透明的分布式基础框架
Hadoop的核心是HDFS和MapReduce,HDFS为海量的数据提供了存储,而MapReduce为海量的数据提供了计算。
分布式文件系统把文件分布存储到多个计算机节点上,成千上万的计算机节点构成计算机集群。
Hadoop Distributed File System
Hadoop 分布式文件系统,是指被设计成适合运行在通用硬件上的分布式文件系统
HDFS只设置了一个名称节点(主节点)
数据节点是分布式文件系统HDFS的工作节点,负责数据的存储和读取,会根据客户端或者是名称节点的调度来进行数据的存储和检索,并向名称节点定期发送自己所存储的块的列表。
每个数据节点中的数据会被保存在各自节点的本地linux文件系统中。
Bigtable是一个分布式存储系统,起初用于解决典型的互联网搜索问题。
HBase是一个高可靠、高性能、面向列、可伸缩的分布式数据库,是谷歌BigTable的开源实现,主要用来存储非结构化和半结构化的松散数据,HBase的目标是处理非常庞大的表,可以通过水平扩展的方式,利用连接计算机集群处理有超过10亿行数据和数百万列元素组成的数据表。
Zookeeper是一个分布式的,开发码源的分布式应用程序协调服务,是Hadoop和HBase的重要组件。
CPU性能大约每隔18个月翻一番
从2005年开始摩尔定律逐渐失效
一种编程模型,将复杂的,运行与大规模集群上的并行计算过程高度地抽象到了两个函数:Map(映射)和Reduce(归约)。
采用分治的思想,让“计算向数据靠拢”,而不是“数据向计算靠拢”(挪动数据需要大量网络开销)
第二名称节点是HDFS架构中的一个重要组成部分,他是用来保存名称节点中对HDFS元数据信息的备份,并减少名称节点重启的时间。一般单独运行在一台机器上。
Hadoop可以很好地解决大规模数据的离线批量处理问题,但是受限于Hadoop MapReduce编程框架的高延迟数据初级机制,是得Hadoop无法满足大规模数据试试处理应用的需求。
传统并行计算框架 | MapReduce | |
---|---|---|
集群架构/容错性 | 共享式(共享内存/共享存储),容错性差 | 非共享式,容错性好 |
硬件/价格/扩展性 | 刀片服务器、高速网、SAN,价格贵,扩展性差 | 普通PC机,便宜,扩展性好 |
编程/学习难度 | what-how,难 | what,简单 |
适用场景 | 实时、细粒度计算、计算密集型 | 批处理、非实时、数据密集型 |