-
2007-06-06
并行程序设计2 - [并行计算]
版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://xingzhesun.blogbus.com/logs/5676956.html
第6章 六个接口构成的MPI子集MPI_1 128个调用接口MPI-2 278个调用接口6.1子集介绍6.1.1MPI调用的参数说明6.1.2MPI初始化 int MPI_Init(int *argc, char ***argv)6.1.3MPI结束 int MPI_Finalize(void)6.1.4MPI当前进程标识 int MPI_Comm_rank(MPI_Comm comm, int *rank)6.1.5MPI通信域包含的进程数 int MPI_Comm_size(MPI_Comm comm, int *size)6.1.6MPI消息发送 int MPI_Send(void* buf, int count, MPI_Datatype, int dest, int tag, MPI_Comm comm)6.1.7MPI消息接收 int MPI_Recv(void*buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)6.1.8MPI返回状态 有三个域 MPI_SOURCE, MPI_TAG, MPI_ERROR 对status变量执行MPI_GET_COUNT调用可以得到接收的消息的长度信息6.2 MPI预定义数据类型6.3 MPI数据类型匹配和数据转换两个方面:宿主语言的类型和通信操作所指定的类型匹配;发送方和接收方的类型匹配类型匹配规则:有类型数据的通信,发送方和接收方均使用相同的数据类型 无类型数据的通信,发送方和接收方均以MPI_BYTE作为数据类型 打包数据的通信,发送方和接收方均使用MPI_PACKED数据转换: 数据类型的转换;数据表示的转换***.1MPI消息的组成信封:<源/目, 标识, 通信域>数据: <起始地址, 数据个数, 数据类型>***.2任意源和任意标识一个接收操作可以接收任何发送者的消息,而一个发送操作,则必须指明一个单独的接收者.MPI_AMY_SOURCE MPI_ANY_TAG***.3 MPI通信域包括:进程组和通信上下文. 第7章 简单的MPI程序示例7.1用MPI实现计时功能double MPI_Wtime(void) double starttime,endtime;...starttime = MPI_Wtime(); ... endtime = MPI_Wtime();printf("That tooks %f secodes\n", endtime - starttime); double MPI_Wtick();返回MPI_Wtime的精度,单位是秒。测试时钟是否准确。7.2获取机器的名字和MPI版本号int MPI_Get_processor_name(char* name, int* resultlen);int MPI_Get_version(int* version, int* subversion);7.3是否初始化及错误退出int MPI_Initialized(int* flag)int MPI_Abort(MPI_Comm comm, int errorcode)下面的例子将指定的master结点杀掉 #include"mpi.h"#include<stdio.h> 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){ mastermode = 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();} 7.4数据接力传送ws2_32.lib mpichd.lib ws2_32.lib mpich.lib 7.6任意源和任意标识的使用在接收中,通过使用任意源和任意tag标识,使得该接收操作可以接收任何进程以任何标识发给本进程的数据,但是该消息的数据类型必须和接收操作的数据类型一致。 第8章MPI并行程序的两种基本模式8.1对等模式的MPI程序设计8.1.1jacobi迭代8.1.4虚拟进程虚拟进程MPI_PROC_NULL,是不存在的假想进程,在MPI中的主要作用是充当真实进程通信的目或源,当一个真实进程向一个虚拟进程发送数据或者从一个虚拟进程接收数据时,该真实进程会立刻正确返回,如同执行一个空操作。8.2主从模式的MPI程序设计
#include "stdafx.h"
#include <stdio.h>
#include <mpi.h>//进程接力
// int main(int argc, char* argv[])
// {
// int rank, value, size;
// MPI_Status status;
// MPI_Init(&argc, &argv);
// MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// MPI_Comm_size(MPI_COMM_WORLD, &size);
// do
// {
// //发送数据
// if (rank == 0){
// fprintf(stderr, "n\Please give new value = ");
// //进程0读入要传入的数据
// scanf("%d", &value);
// fprintf(stderr, "%d read << (%d)\n", rank, value);
// //若不小于一个进程则向下一个进程传递数据
// if ( 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);
// }
//
// }else{//接收数据
// MPI_Recv(&value, 1, MPI_INT, rank -1, 0, MPI_COMM_WORLD, &status);
// //MPI_Get_count(&status,)
// fprintf(stderr, "%d receive(%d) << >> %d\n", rank, value,rank- 1);
// if (rank < size -1 ){
// //如不是最后一个进程则将数据继续向后传递
// MPI_Send(&value, 1, MPI_INT, 0, rank + 1, MPI_COMM_WORLD);
// fprintf(stderr, "%d send (%d)>> %d\n", rank, value, rank+1);
// }
// }
//
// //执行同步,将前后两次数据传递分开
// MPI_Barrier(MPI_COMM_WORLD);
// } while(value >= 0);
//
// MPI_Finalize();
// printf("Hello World!\n");
// return 0;
// }
//
//进程之间相互问候// void Hello(void);
//
// int main(int argc, char* argv[])
// {
// int me, option, namelen, size;
//
// char processor_name[MPI_MAX_PROCESSOR_NAME];
// MPI_Init(&argc, &argv);
// MPI_Comm_rank(MPI_COMM_WORLD, &me);
// MPI_Comm_size(MPI_COMM_WORLD, &size);
//
// if (size < 2){
// //如果总的进程数小于2, 则出错推出
// fprintf(stderr, "system require at least 2 processes.");
// MPI_Abort(MPI_COMM_WORLD, 1);
// }
//
// //get current name
// MPI_Get_processor_name(processor_name, &namelen);
//
// fprintf(stderr, "Process &d is alive on &s\n", me, processor_name);
//
// //sync
// MPI_Barrier(MPI_COMM_WORLD);
//
// //greet each other
// Hello();
//
// //
// MPI_Finalize();
//
// return 0;
// }
//
// void Hello(void){
//
// int nproc, me;
// int type =1;
// int buffer[2], node;
// MPI_Status status;
// MPI_Comm_rank(MPI_COMM_WORLD, &me);
// MPI_Comm_size(MPI_COMM_WORLD, &nproc);
//
// if (me == 0){
// //进程0负责打印提示信息
// printf("\nHello test from all to all\n");
// fflush(stdout);
// }
//
// //循环对每个进程进行问候
// for (node = 0; node < nproc; node++){
// if (node != me){
// buffer[0]= me;
// buffer[1]= node;//greet node
//
// //send information to node
// MPI_Send(buffer, 2, MPI_INT, node, type, MPI_COMM_WORLD);
//
// //receive information from node
// //question 1. blocked or not blocked
// //question 2. when MPI_Recv returns, the information must be sent from node!
// MPI_Recv(buffer, 2, MPI_INT, node, type, MPI_COMM_WORLD, &status);
//
// //error if receiving information is not sent to me or
// //????
// if ((buffer[0] != node )||(buffer[1] != me)){
// (void)fprintf(stderr, "Hello: %d!=%d or %d!=d%\n", buffer[0], node, buffer[1], me);
// }else{
// //receiving informaton
// printf("Hello from %d to %d\n", me, node);
// }
//
//
//
// fflush(stdout);
// }
// }
//
// }
//接收其他进程的数据
// int main(int argc, char** argv){
// int rank;
// int size;
// int i;
// int buf[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 (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 (i=0; i < 100; i++){
// buf[0]=rank+i;
// MPI_Send(buf, 1, MPI_INT, 0, i, MPI_COMM_WORLD);
//
// }
// }
//
// MPI_Finalize();
//}//对等模式的MPI程序设计
// const int totalsize = 16;
// const int mysize = totalsize/4;
// const int steps = 10;
// int aa[2][3]={{1,1,1},{3,3,3}};
// int a[totalsize][mysize + 2];
// int b[totalsize][mysize + 2];
//
// int n, myid, numprocs, i, j, rc;
//
// int main(int argc, char** argv){
// int begin_col;
// int end_col;
// int ierr;
//
// MPI_Status status;
//
// MPI_Init(&argc, &argv);
// MPI_Comm_rank(MPI_COMM_WORLD, &myid);
// MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
//
// //数组初始化
// for (j = 1; j < mysize+2; j++){
// for (i=1; i < totalsize; i++){
// a[i][j] = 0.0;
// }
// }
//
// //
// if (myid == 0){
// for (i = 1; i < totalsize; i++){
// a[i][2] = 8.0;
// }
// }
//
// //
// if (myid == 3){
// for (i = 1; i < totalsize; i++){
// a[i][mysize + 1] = 8.0;
// }
// }
//
// //
// for (i = 1; i < mysize; i++){
// a[1][i] = 8.0;
// a[totalsize][i] = 8.0;
// }
//
//
// //jacobi迭代部分
// for (n = 1; n < steps; n++){
// //从右侧的邻居得到数据
// if (myid < 3){
// MPI_Recv(&a[1][mysize + 2],totalsize, MPI_INT, myid + 1, 10, MPI_COMM_WORLD, &status);
// }
//
// //向左侧的邻居发送数据
// if (myid > 0){
// MPI_Send(&a[1][2], totalsize, MPI_INT, myid, 10, MPI_COMM_WORLD);
// }
//
// //向右侧邻居发送数据
// if (myid < 3){
// MPI_Send(&a[1][mysize+1], totalsize, MPI_INT, myid + 1, 10, MPI_COMM_WORLD);
// }
//
// //向左侧邻居接收数据
// if (myid > 0)
// {
// MPI_Recv(&a[1][1], totalsize, MPI_INT, myid - 1, 10, MPI_COMM_WORLD, &status);
// }
//
// //
// begin_col = 2;
// end_col = mysize + 1;
// //
// if (myid == 0){
// begin_col = 3;
// }
// //
// if (myid == 3){
// end_col = mysize;
// }
//
// //
// for(j = begin_col; j < end_col; j++){
// for (i = 2; i < totalsize - 1; i++){
// b[i][j] = (a[i][j+1] + a[i][j-1] + a[i+1][j] + a[i-1][j])*0.25;
// }
// }
//
// for(j = begin_col; j < end_col; j++){
// for (i = 2; totalsize-1; i++){
// a[i][j]= b[i][j];
//
// }
// }
// }
//
// for (i = 2; i < totalsize; i++){
// //printf()
// }
//
// MPI_Finalize();
// return 0;
//}主从模式的MPI程序设计
void master_io();
void slave_io();
#define MSG_EXIT 1
#define MSG_PRINT_ORDERED 2
#define MSG_PRINT_UNORDERED 3int main(int argc, char** argv){
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0)
{
master_io();
}else{
slave_io();
}MPI_Finalize();
}void master_io(){
int i, j, size, nslave, firstmsg;
char buf[256], buf2[256];
MPI_Status status;
MPI_Comm_size(MPI_COMM_WORLD, &size);
nslave = size -1;
while (nslave > 0){
//从任意进程接收任意标识的消息
MPI_Recv(buf, 256, MPI_CHAR, MPI_ANY_SOURCE, MPI_ANY_TAG,MPI_COMM_WORLD, &status);
switch(status.MPI_TAG)
{
case MSG_EXIT: nslave--; break;
case MSG_PRINT_UNORDERED:fputs(buf, stdout);break;
case MSG_PRINT_ORDERED:
firstmsg = status.MPI_SOURCE;
for (i=1; i< size; i++){
if (i == firstmsg){
fputs(buf, stdout);
}else{
//指定源进程和消息标识
MPI_Recv(buf2, 256, MPI_CHAR, i, MSG_PRINT_ORDERED, MPI_COMM_WORLD, &status);
fputs(buf2, stdout);
}
}
break;
}
}
}void slave_io(){
char buf[256];
int rank;
MPI_Comm_rank(MPI_COMM_WORLD, & rank);
sprintf(buf, "Hello from slave&d, ordered print\n", rank);//send ordered msg
MPI_Send(buf, strlen(buf)+1, MPI_CHAR, 0, MSG_PRINT_ORDERED, MPI_COMM_WORLD);sprintf(buf, "Goodbye from slave %d, ordered print\n", rank);
//send unordered msg
MPI_Send(buf, strlen(buf)+1, MPI_CHAR, 0, MSG_PRINT_UNORDERED, MPI_COMM_WORLD);//send exit msg
MPI_Send(buf, 0, MPI_CHAR, 0, MSG_EXIT, MPI_COMM_WORLD);}
随机文章:
SQL查询 2009-06-26RDF and template 2007-07-31并行程序设计1 2007-05-10string alloced memory on the heap or stack 2007-02-02#pragma是什么意思 2006-11-23
收藏到:Del.icio.us








评论
进程得到一个数加一传递给下个进程
#include "mpi.h"
#include <stdio.h>
void main(int argc, char* argv[])
{
int a=0;
int myid,numprocs;
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
MPI_Comm_rank(MPI_COMM_WORLD,&myid);
if(myid==0)
{
printf("Enter the number:");
scanf("%d",&a);
}
if(numprocs>1)
{
for(myid=0;myid<numprocs;myid++)
{
a=a+1;
MPI_Send(&a,1,MPI_INT,myid+1,0,MPI_COMM_WORLD);
MPI_Recv(&a,1,MPI_INT,myid,0,MPI_COMM_WORLD,&status);
printf("%d",a);
}
MPI_Send(&a,1,MPI_INT,0,1,MPI_COMM_WORLD);
MPI_Recv(&a,1,MPI_INT,myid-1,1,MPI_COMM_WORLD,&status);
}
printf("Result is:");
printf("%d",a);
MPI_Finalize();
}
///////////////////////////////////////
在run界面运行进程数大于2就错误
当进程数大于1时,你要考虑(0和最后一个进程要特殊考虑)首先接受前一个进程的数据,然后在向下一个进程发送数据。
if(numprocs>1)
{
if(myid==0)
{send data to myid+1}
else if (myid < numprocs-1)
{receive data from myid-1;
send data to myid+1;}
if(myid==numprocs-1)
{receive data from myid-1;}
}
我觉得你还在用我们串行程序的设计思路在,设计并行程序。
关于进程的边界问题,你可设计虚拟进程,这样就不必对边界进程给与特殊的考虑了。
不知回答是否正确,你验证吧。
有问题在联系。
我的 msn:sunhaimin2006@tom.com