⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpi55.htm

📁 该文件为mpich2的开发文档
💻 HTM
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
   <TITLE> ICPSEP Content
</TITLE>
   <META NAME="GENERATOR" CONTENT="Mozilla/3.0Gold (Win95; I) [Netscape]">
</HEAD>
<BODY BGCOLOR="#F0F8FF">

<TABLE WIDTH="100%" >
<TR>
<TD align=left><FONT SIZE=+2>5.5 针对性例子</FONT></TD>

<TD align=right><A HREF="mpi54.htm" tppabs="http://arch.cs.pku.edu.cn/parallelprogramming/mpispec/mpi54.htm"><IMG SRC="backward.gif" tppabs="http://arch.cs.pku.edu.cn/image/backward.gif" ALT="BACKWARD" HEIGHT=32 WIDTH=32></A>
<A HREF="mpi56.htm" tppabs="http://arch.cs.pku.edu.cn/parallelprogramming/mpispec/mpi56.htm"><IMG SRC="forward.gif" tppabs="http://arch.cs.pku.edu.cn/image/forward.gif" ALT="FORWARD" HEIGHT=32 WIDTH=32></A></TD>
</TR>
</TABLE>

<P>
<HR WIDTH="100%"></P>

<P><A NAME="5.5.1"></A><FONT SIZE=+1>5.5.1当前练习#1</FONT></P>

<P>例#1a: </P>

<P> main(int argc,char **argv)<BR>
 {<BR>
  int me,size;<BR>
  ... <BR>
  MPI_Init(&amp;argc,&amp;argv); <BR>
  MPI_Comm_rank(MPI_COMM_WORLD,&amp;me); <BR>
  MPI_Comm_size(MPI_COMM_WORLD,&amp;size); </P>

<P>  (void)printf(&quot;Process %d size %d&quot;,me,size); <BR>
  ... <BR>
  MPI_Finalize();<BR>
 }</P>

<P>例#1a是一个对自身进行合法初始化但不做任何事的程序,程序中引用了&quot;all&quot;
通信 子并打印了一个消息。其自身也能合法终止。该例不意味着MPI本身支持类printf通信。
</P>

<P>例#1b(假设size是偶数) </P>

<P> main(int argc,char **argv) <BR>
 {<BR>
  int me,size; <BR>
  int SOME_TAG=0; <BR>
  ... <BR>
  MPI_Init(&amp;argc,&amp;argv); </P>

<P>  MPI_Comm_rank(MPI_COMM_WORLD,&amp;me);/*本地*/ <BR>
  MPI_Comm_size(MPI_COMM_WORLD,&amp;size);/*本地*/ </P>

<P>  if ((me%2)==0)<BR>
  {<BR>
   /*如果不是最高编号的进程则发送*/ <BR>
   if((me+1)&lt;size)<BR>
    MPI_Send(...,me+1,SOME_TAG,MPI_COMM_WORLD);<BR>
   }<BR>
   else <BR>
    MPI_Recv(...,me-1,SOME_TAG,MPI_COMM_WORLD);</P>

<P>   ...<BR>
   MPI_Finalize(); <BR>
  }</P>

<P>例#1b有计划地阐述了&quot;all&quot;通信子中奇偶进程间的消息交换.</P>

<P><A NAME="5.5.2"></A><FONT SIZE=+1>5.5.2 当前练习#2 </FONT></P>

<P> main(int argc,char **argv)<BR>
 {<BR>
  int me,count; <BR>
  void *data;<BR>
  ... </P>

<P>  MPI_Init(&amp;argc,&amp;argv);<BR>
  MPI_Comm_rank(MPI_COMM_WORLD,&amp;me);</P>

<P>  if(me==0) <BR>
  {<BR>
   /*得到输入,建立缓冲区&quot;data&quot;*/ <BR>
   ...<BR>
   }</P>

<P>   MPI_Bcast(data,count,MPI_BYTE,0,MPI_COMM_WORLD);</P>

<P>   ...</P>

<P>   MPI_Finalize(); <BR>
  }</P>

<P>本例阐述了集合通信的使用.</P>

<P><A NAME="5.5.3"></A><FONT SIZE=+1>5.5.3(近似)当前练习#3</FONT></P>

<P> main(int argc,char **argv)<BR>
 {<BR>
  int me,count,count2; <BR>
  void *send_buf,*recv_buf,*send_buf2,*recv_buf2; <BR>
  MPI_Group MPI_GROUP_WORLD,grprem; <BR>
  MPI_Comm commslave; <BR>
  static int rank[]={0};<BR>
  ...<BR>
  MPI_Init(&amp;argc,&amp;argv);<BR>
  MPI_Comm_group(MPI_COMM_WORLD,&amp;MPI_GROUP_WORLD); <BR>
  MPI_Comm_rank(MPI_COMM_WORLD,&amp;me);/*本地/</P>

<P>  MPI_Group_excl(MPI_GROUP_WORLD,1,ranks,&amp;grprem);/*本地*/   MPI_Comm_create(MPI_COMM_WORLD,grprem,&amp;commslave);</P>

<P>  if((me!=0)<BR>
  {<BR>
   /*在从机上计算*/ <BR>
   ...<BR>
   MPI_Reduce(send_buf,recv_buff,count,MPI_INT,MPI_SUM,1,commslave);<BR>
   ...<BR>
   }<BR>
   /*0则立即作此归约操作,其它则稍后再做*/ <BR>
   MPI_Reduce(send_buf2,recv_buff2,count2, MPI_INT,MPI_SUM,0,MPI_COMM_WORLD);</P>

<P>   MPI_Comm_free(&amp;commslave); <BR>
   MPI_Group_free(&amp;MPI_GROUP_WORLD); <BR>
   MPI_Group_free(&amp;grprem); <BR>
   MPI_Finalize(); <BR>
   }</P>

<P>本例阐述了如何创建一个组,该组包含了除&quot;all&quot;组中第0个进程之外的所有进程,同时阐述了如何为该新组(commslave)形成一个通信子。此新通信子在一个集合调用中被使用,而且所有进程在上下文MPI_COMM_WORLD中都执行一个集合调用。本例还阐述了两个通信子(本质上具有不同的上下文)如何保护通信。亦即,MPI_COMM_WORLD中的通信与commslave中的通信隔离开,反之亦然。</P>

<P>概要地讲,“组安全性”是通过通信子获得的,这是因为在任何进程上通信子内的不同上下文被强制为唯一的。</P>

<P><A NAME="5.5.4"></A><FONT SIZE=+1>5.5.4 例#4 </FONT></P>

<P>下面的例子目的是阐述点对点与集合通信之间的安全性。MPI保证了单独一个通信子能够安全地进行点对点与集合通信。</P>

<P> #define TAG_ARBITRARY 12345<BR>
 #define SOME_COUNT 50</P>

<P> main(int argc,char **argv)<BR>
 {<BR>
  int me;<BR>
  MPI_Request request[2];<BR>
  MPI_Status status[2];<BR>
  MPI_Group MPI_GROUP_WORLD,subgroup; <BR>
  int ranks[]={2,4,6,8};<BR>
  MPI_Comm the_comm;<BR>
  ... <BR>
  MPI_Init(&amp;argc,&amp;argv);<BR>
  MPI_Comm_group(MPI_COMM_WORLD,&amp;MPI_GROUP_WORLD); </P>

<P>  MPI_Group_incl(MPI_GROUP_WORLD,4,ranks,&amp;subgroup);/*本地*/<BR>
  MPI_Group_rank(subgroup,&amp;me);/*本地*/ </P>

<P>  MPI_Comm_create(MPI_COMM_WORLD,subgroup,&amp;the_comm);</P>

<P>  if (me!=UNDEFINED)<BR>
  {<BR>
   MPI_Irecv(buff1,count,MPI_DOUBLE,MPI_ANY_SOURCE,TAG_ARBITRARY,the_comm,
request);       MPI_Isend(buff2,count,MPI_DOUBLE,(me+1)%4,TAG_ARBITRARY,
the_comm,request+1);<BR>
   }</P>

<P>   for(i=0;i&lt;SOME_COUNT;i++)<BR>
   MPI_Reduce(...,the_comm);<BR>
   MPI_Waitall(2,request,status);</P>

<P>   MPI_Comm_free(&amp;the_comm);<BR>
   MPI_Group_free(&amp;MPI_GROUP_WORLD);<BR>
   MPI_Group_free(&amp;subgroup);<BR>
   MPI_Finalize();<BR>
  }</P>

<P><A NAME="5.5.5"></A><FONT SIZE=+1>5.5.5 库例#1 </FONT></P>

<P>主程序:</P>

<P> main(int argc,char **argv)<BR>
 {<BR>
  int done=0; <BR>
  user_lib_t *libh_a,*libh_b;<BR>
  void *dataset1,*dataset2;<BR>
  ...<BR>
  MPI_Init(&amp;argc,&amp;argv);<BR>
  ...<BR>
  init_user_lib(MPI_COMM_WORLD,&amp;libh_a); <BR>
  init_user_lib(MPI_COMM_WORLD,&amp;libh_b);<BR>
  ...<BR>
  user_start_op(libh_a,dataset1);<BR>
  user_start_op(libh_b,dataset2);<BR>
  ...<BR>
  while(!done) <BR>
  {<BR>
   /*起作用*/ <BR>
   ...<BR>
   MPI_Reduce(...,MPI_COMM_WORLD); <BR>
   ... <BR>
   /*如果done,则见下面*/ <BR>
   ...<BR>
   }<BR>
   user_end_op(libh_a);<BR>
   user_end_op(libh_b); </P>

<P>   uninit_user_lib(libh_a); <BR>
   uninit_user_lib(libh_b); <BR>
   MPI_Finalize();<BR>
  }</P>

<P>用户库初始化代码: <BR>
 void init_user_lib(MPI_Comm *comm,user_lib_t **handle)<BR>
 {<BR>
  user_lib_t *save;</P>

<P>  user_lib_initsave(&amp;save);/*本地*/ <BR>
  MPI_Comm_dup(comm,&amp;(save-&gt;comm));</P>

<P>  /*其它初始化*/ <BR>
  ...</P>

<P>  *handle=save;<BR>
 }</P>

<P>用户启动代码: <BR>
 void user_start_op(user_lib_t *handle,void *data)<BR>
 {<BR>
  MPI_Irecv(...,handle-&gt;comm,&amp;(handle-&gt;irecv_handle)); <BR>
  MPI_Isend(...,handle-&gt;comm,&amp;(handle-&gt;irecv_handle)); <BR>
 }</P>

<P>用户通信清除代码:</P>

<P> void user_end_op(usr_lib_t *handle)<BR>
 {<BR>
  MPI_Status *status; <BR>
  MPI_Wait(handle-&gt;isend_handle,status); <BR>
  MPI_Wait(handle-&gt;irecv_handle,status); <BR>
  }</P>

<P>用户对象清除代码: </P>

<P> void uninit_user_lib(user_lib_t *handle)<BR>
 {<BR>
  MPI_Comm_free(&amp;(handle-&gt;comm));<BR>
  free(handle);<BR>
  }</P>

<P><A NAME="5.5.6"></A><FONT SIZE=+1>5.5.6 库例#2</FONT></P>

<P>主程序:<BR>
 main(int argc **argv) <BR>
 {<BR>
  int ma, mb; <BR>
  MPI_Group MPI_GROUP_WORLD,group_a, group_b; <BR>
  MPI_Comm comm_a,commb; </P>

<P>  static int list_a[] = {0,1};<BR>
#if defined(EXAMPLE_2B) |defined(EXAMPLE_2C)<BR>
  static int list_b[] = {0, 2, 3}; </P>

<P>#else/* EXAMPLE_2A */ <BR>
  static int list_b[] = {0, 2};<BR>
#endif<BR>
  int size_list_a = sizeof(list_a)/sizeof(int); <BR>
  int size_list_b = sizeof(list_b)/sizeof(int); </P>

<P>  ...<BR>
  MPI_Init(&amp;argc, &amp;argv);<BR>
  MPI_Comm_group(MPI_COMM_WORLD, &amp;MPI_GROUP_WORLD); </P>

<P>  MPI_Group_incl(MPI_GROUP_WORLD,size_list_a,&amp;group_a); <BR>
  MPI_group_incl(MPI_GROUP_WORLD,size-list_b,&amp;group_b); </P>

<P>  MPI_Comm_create(MPI_COMM_WORLD,group_a, &amp;comm_a); <BR>
  MPI_Comm_create(MPI_COMM_WORLD,group_b, &amp;comm_b); </P>

<P>  MPI_Comm_rank(comm_a, &amp;ma);<BR>
  MPI_Comm_rant(comm_b, &amp;mb); </P>

<P>  if(ma != MPI_UNDEFINED) <BR>
   lib_call(comm_a); </P>

<P>  if(mb != MPI_UNDEFINED)<BR>
  {<BR>
   lib_call(comm_b); <BR>
   lib_call(comm_b);<BR>
   }</P>

<P>  MPI_Comm_free(&amp;comm_a); <BR>
  MPI_Comm_free(&amp;comm_b);<BR>
  MPI_Group_free(&amp;group_a);<BR>
  MPI_Group_free(&amp;group_b); <BR>
  MPI_Group_free(&amp;MPI_GROUP_WORLD);<BR>
  MPI_Finalize(); <BR>
  }</P>

<P>库:</P>

<P> void lib_call(MPI_Comm comm)<BR>
 {<BR>
  int me, done = 0;<BR>
  MPI_Comm_rank(comm,&amp;me);<BR>
  if(me == 0)<BR>
   while(!done)<BR>
   {<BR>
    MPI_Recv(..., MPI_ANY_SOURCE, MPI_ANY_TAG, comm);<BR>
    ...<BR>
    }<BR>
   else<BR>
   {<BR>
   /*起作用*/ <BR>
   MPI_Send(...,0, ARBITRARY_TAG, comm);<BR>
   ...<BR>
   }<BR>
#ifdef EXAMPLE_2C<BR>
   /* 包含(resp, exclude)用于safety (resp, no safety): */ <BR>
   MPI_Barrier(comm); <BR>
#endif<BR>
  }</P>

<P>根据程序是否在lib_b中包含序列号等级3,以及是否在lib_call中进行同步,可将上面的例子实际
上当做三个例子.本例所阐述的是,不管上下文如何,使用同样上下文对lib_call进行的后续调用相互间无须是安全的(口语上,成为“后标志”).
如果加上MPI_Barrier, 就要考虑安全性.已经证明,即使使用上下文, 库也要仔细书写.当不包括序列号3时,就无须通过同步来从后标志中获取安全性.
</P>

<P>假如MPI提供基本的保证,则类似于&quot;reduce&quot;和&quot;allreduce&quot;这样的算法就会有足够强大的选
择特性来保证其固有的正确性(无后标志).对使用相同的根和不同的根的典型树广播算法的多重调用也是这样.
这里我们依赖于MPI的两个保证: 同一上下文内的进程间的成对顺序,及资源的可选择性--删除任一个特征就等于去掉了不要求后标志这一保证.
</P>

<P>试图作非确定性广播或包括通配符操作的其它调用一般不具备诸如 &quot;reduce&quot;,&quot;allreduce&quot;,及&quot;broadcast&quot;这种确定性实现的好的特性.这种算法必须利用单调上升的标志(在一个通信子范围内)来保持正确性.
</P>

<P>前面的所有调用都假定是用点对点操作来实现集合调用.MPI实现既可用也可不用点对点操作来实现集合调用.这些算法用于阐述正确性和安全性问题,而不管MPI如何实现其集合调用.
见<A HREF="mpi58.htm" tppabs="http://arch.cs.pku.edu.cn/parallelprogramming/mpispec/mpi58.htm">5.8节</A>.</P>

<P>
<HR WIDTH="100%"></P>

<TABLE WIDTH="100%" >
<TR>
<TD align=left>Copyright: NPACT </TD>

<TD align=right><A HREF="mpi54.htm" tppabs="http://arch.cs.pku.edu.cn/parallelprogramming/mpispec/mpi54.htm"><IMG SRC="backward.gif" tppabs="http://arch.cs.pku.edu.cn/image/backward.gif" ALT="BACKWARD" HEIGHT=32 WIDTH=32></A>
<A HREF="mpi56.htm" tppabs="http://arch.cs.pku.edu.cn/parallelprogramming/mpispec/mpi56.htm"><IMG SRC="forward.gif" tppabs="http://arch.cs.pku.edu.cn/image/forward.gif" ALT="FORWARD" HEIGHT=32 WIDTH=32></A>
</TD>
</TR>
</TABLE>

</BODY>
</HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -