并行归并排序——MPI

博客介绍了如何使用MPI实现并行归并排序。每个进程首先生成并排序局部数据,然后通过树形通信结构将排序后的数据逐层合并,最终由进程0收集并打印全局排序结果。文章详细阐述了树形通信中父子节点的确定方法,并提供了编译及运行程序的指令。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

      并行归并排序在程序开始时,会将n/comm_comm个键值分配给每个进程,程序结束时,所有的键值会按顺序存储在进程0中。为了做到这点,它使用了树形结构通信模式。当进程接收到另一个进程的键值时,它将该键值合并进自己排序的键值列表中。编写一个程序实现归并排序。进程0应该读入n的值,将其广播给其余进程。每个进程需要使用随机数生成器来创建n/comm_sz的局部int型数据列表。每个进程先排序各自的局部列表,然后进程0收集并打印这些局部列表。然后,这些进程使用树形结构通信合并全局列表给进程0,并打印最终结果。

  

如图,一般情况下,应由进程读入数据,然后一层一层的传到每个进程,每个进程排序完成之后,由上一层的进程进行合并。我这次做的只是输入数n,由每个进程产生n/comm_sz个随机数。

这里有一个问题,如何确定一个进程的父节点和子节点?

  你最初可能认为让在处理树中的每个节点是一个单独的进程中。这样,你可以简单地从二叉堆借用一个想法任何父节点的左子节点的下标2* K+1,右子节点的下标是2* K+2,一个节点的父节点是(K-1 )/ 2,这在一个完全二叉树中确定了父子关系。因此,一个内部节点将数据分成两半,并发送给每个子进程进行处理。这样叶节点,只是做了排序,内部节点等待然后从两个子节点接收回数据,执行两半的合并,以及(对于所有内部节点但非根节点本身)将结果发送到父节点。

  但是这样带来一个问题,就是当叶节点进行排序时,父节点在等待子节点,没有理由让父节点空闲等待子节点进行排序,我们希望让父节点充当左子节点进行工作,如图:
http://penguin.ewu.edu/~trolfe/ParallelMerge/PMerge_B.gif
  这样每个节点将数据分成两半,每个节点自己处理数据的左半,右子节点处理数据的右半。这样之后你就要确定每个节点的父节点和子节点,你可以根据树形通信结构来确定每个节点的父节点和子节点。
  我们要先确定每个节点在树形通信结构的高度,叶节点的高度为0,这样根节点0的高度是3。节点0需要与节点4进行通信,对于如何计算出节点0的右子节点是4,可以通过将1转化成二进制并左移节点0所在的高度3减1位,即(myRank|(1<<2)),myRank表示节点的编号,这里是0,这样就可以计算出高度为3的节点0的右子节点。下一步节点0需要与节点2通信,节点4需要与节点6通信,此时节点0和4的高度为2,因此需要计算他们的子节点时通过公式((myRank|(1<<1)),这样计算出节点0的右子节点是2,节点4的右子节点时6,一般化的公式是(myRank|(myHeight-1))。
  计算完每个节点的子节点后,还要计算每个节点的父节点,每个节点的父节点可以通过如下公式进行计算,myRank&~(1<<myHeight)。
  下面是一个小的demo来展示通信过程,他展示了高度为3的通信树节点之间的通信过程,
 1 #include <stdio.h>
 2 
 3 void communicate ( int myHeight, int myRank )
 4 {  int parent = myRank & ~(1<<myHeight);
 5 
 6    if ( myHeight > 0 )
 7    {  int nxt     = myHeight - 1;
 8       int rtChild = myRank | ( 1 << nxt );
 9 
10       printf ("%d sending data to %d\n", myRank, rtChild);
11       communicate ( nxt, myRank );
12       communicate ( nxt, rtChild );
13       printf ("%d getting data from %d\n", myRank, rtChild);
14    }
15    if ( parent != myRank )
16       printf ("%d transmitting to %d\n", myRank, parent);
17 }
18 
19 int main ( void )
20 {  int myHeight = 3, myRank = 0;
21 
22    printf ("Building a height %d tree\n", myHeight);
23    communicate(myHeight, myRank);
24    return 0;
2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值