并行归并排序在程序开始时,会将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,这在一个完全二叉树中确定了父子关系。因此,一个内部节点将数据分成两半,并发送给每个子进程进行处理。这样叶节点,只是做了排序,内部节点等待然后从两个子节点接收回数据,执行两半的合并,以及(对于所有内部节点但非根节点本身)将结果发送到父节点。

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