MPI并行编程系列二快速排序
计算流体力学中科院力学所第6讲-MPI并行程序设计初步2-文档资料

通信2) A(1,1,1),A(2,1,1), A(3,1,1) …., A(1,2,1),A(2,2,1),A(3,2,1) ……, A(1,1,2),A(2,1,2),A(3,1,2) ……,
MPI_Type_Vector(P,M,M*N,MPI_Real,My_Type,ierr)
A(1,1) A(1,2) A(1,3) A(1,4) A(2,1) A(2,2) A(2,3) A(2,4) A(3,1) A(3,2) A(3,3) A(3,4)
Stride=3
4块,每块1个元素,跨度为3(个元素)
A(1,1), A(2,1) , A(3,1), A(1,2), A(2,2) , A(3,2), A(1,3), A(2,3), A(3,3), A(1,4), A(2,4), A(3,4)
MPI的消息发送机制—— 两步进行
MPI_Send( A, … ) 发送 MPI_Recv( B, … ) 接收
配合使用
发送 变量A
Copyright by Li Xinliang
接收 到变量B
3
一、 阻塞式通信与非阻塞式通信
阻塞发送
MPI_Send( A, … )
MPI_Recv( B , …)
Part 2 MPI 并行程序设计
1. 阻塞式通信与非阻塞式通信 2. 非连续数据的传送与接收 3. MPI的通信域与组; 算例计算三维差分 4. 分布式数据的存储
Part 3 实例教学
1. 谱方法求解不可压缩N-S方程 2. 利用紧致型差分格式求导数
2 Copyright by Li Xinliang
快速排序算法的并行实现 -回复

快速排序算法的并行实现-回复题目:快速排序算法的并行实现引言:随着计算机硬件的发展和多核处理器的普及,并行计算已成为提高算法性能的重要手段之一。
快速排序算法以其高效的平均时间复杂度而闻名,然而,传统的串行实现方式可能无法充分发挥硬件资源的优势。
因此,本文将介绍快速排序算法的并行实现,旨在提高排序算法的效率。
第一部分:快速排序算法基本原理1.1 快速排序算法简介快速排序算法是一种基于比较的排序算法,通过将待排序序列分成两个子序列,然后分别对子序列进行排序,最后合并成有序序列。
其核心思想是通过选取一个基准元素,将小于基准元素的数移到基准元素的左边,大于基准元素的数移到基准元素的右边,从而实现排序。
1.2 快速排序算法步骤- 选择一个基准元素,通常为序列的第一个元素- 比较待排序元素与基准元素,将小于基准元素的元素移动到基准元素的左边,大于基准元素的元素移动到基准元素的右边- 递归地对基准元素左侧和右侧的子序列进行排序,直到每个子序列只包含一个元素或为空第二部分:串行实现快速排序算法快速排序的串行实现是最基本的实现方式,其核心思想是利用递归将待排序序列不断分割,直到基准元素左右的子序列长度为1或空。
第三部分:并行实现快速排序算法3.1 并行化选取基准元素传统的快速排序算法中,基准元素的选择对算法性能有很大的影响。
在并行实现中,可以通过并行化选取基准元素来加速算法的执行。
具体步骤如下:- 将待排序序列划分为多个子序列,并同时选取每个子序列的中间元素作为候选基准元素- 在多个候选基准元素中选择一个全局基准元素,可以采用并行化的选取方法,例如选择所有候选基准元素的中位数作为全局基准元素3.2 并行化快速排序递归调用在串行实现中,快速排序算法使用递归调用对子序列进行排序。
然而,在并行实现中,递归调用可能导致负载不均衡,因此需要进行并行化处理。
具体步骤如下:- 将待排序序列分成多个子序列,并为每个子序列创建一个任务- 并行地对每个子序列进行递归调用,并等待所有任务的完成- 最后,将所有子序列的结果进行合并,得到有序序列第四部分:并行实现的优势和注意事项4.1 并行实现的优势通过并行化快速排序算法,可以充分发挥多核处理器的优势,提高排序的速度和算法的效率。
(完整word版)并行计算实验快速排序的并行算法

3。
1实验目的与要求1、熟悉快速排序的串行算法2、熟悉快速排序的并行算法3、实现快速排序的并行算法3。
2 实验环境及软件单台或联网的多台PC机,Linux操作系统,MPI系统。
3.3实验内容1、快速排序的基本思想2、单处理机上快速排序算法3、快速排序算法的性能4、快速排序算法并行化5、描述了使用2m个处理器完成对n个输入数据排序的并行算法.6、在最优的情况下并行算法形成一个高度为log n的排序树7、完成快速排序的并行实现的流程图8、完成快速排序的并行算法的实现3.4实验步骤3.4。
1、快速排序(Quick Sort)是一种最基本的排序算法,它的基本思想是:在当前无序区R[1,n]中取一个记录作为比较的“基准”(一般取第一个、最后一个或中间位置的元素),用此基准将当前的无序区R[1,n]划分成左右两个无序的子区R[1,i-1]和R[i,n](1≤i≤n),且左边的无序子区中记录的所有关键字均小于等于基准的关键字,右边的无序子区中记录的所有关键字均大于等于基准的关键字;当R[1,i—1]和R[i,n]非空时,分别对它们重复上述的划分过程,直到所有的无序子区中的记录均排好序为止。
3.4.2、单处理机上快速排序算法输入:无序数组data[1,n]输出:有序数组data[1,n]Begincall procedure quicksort(data,1,n) Endprocedure quicksort(data,i,j)Begin(1) if (i<j) then(1。
1)r = partition(data,i,j)(1。
2)quicksort(data,i,r—1);(1.3)quicksort(data,r+1,j);end ifEndprocedure partition(data,k,l)Begin(1)pivo=data[l](2) i=k-1(3)for j=k to l—1 doif data[j]≤pivo theni=i+1exchange data[i] and data[j]end ifend for(4)exchange data[i+1] and data[l](5) return i+1End3.4.3、快速排序算法的性能主要决定于输入数组的划分是否均衡,而这与基准元素的选择密切相关。
基于MPI的分布式并行排序算法的实现

基于MPI的分布式并行排序算法的实现(信息工程学院,计算机系,计算机科学与技术专业凌广杰)(学号:2000131031)内容提要:本论文采用MPI(Message Passing Interface)在由独立处理器构成的计算机网络上实现了一个称之为IPBPS(Interconnected Processor-Based Parallel Sorting)的分布式并行排序算法。
IPBPS算法是基于一个特定的网络拓扑结构上,它的实现主要分为并行计数排序与归并排序两大模块。
采用MPI来实现IPBPS算法,利用MPI消息传递的同步机制,很好地解决了不同处理器间消息传递的同步问题。
每个处理器运行相同的程序,运行时间也几乎相同,计算负载均匀分布在网络上的每个处理器中,因此并行加速比较高。
关键词:MPI,并行排序,并行程序设计,分布式程序设计教师点评:该论文基于消息传递的并行计算模型,在多台独立互联的计算机上采用MPI(消息传递接口)实现了IPBPS分布式并行排序算法。
针对该具体问题,在任务分配、进程通信与同步、以及采用MPI构建IPBPS算法基于的虚拟网络结构上提出了自己的设想与实现方案。
解决了在由多计算机构成的分布式计算平台上不同计算机之间计算负载的均分、通信与同步等问题。
该论文具有一定的创新性,对基于MPI的并行与分布式程序设计具有一定的示范作用。
论文的表达书写也比较好。
(点评教师:陆楠。
副教授)1. 引言排序计算是计算机应用中最基本的运算之一,在20世纪60年代的计算机厂家就估计,当他们把所有的顾客都考虑在内时,在他们的计算机上,将有超过25%的时间花在排序上[3]。
排序的重要性不言而喻,传统的串行排序算法的速度已不能满足用户的要求。
为了提高排序的速度,人们普遍转向了并行排序算法的研究。
目前大部分并行排序算法的研究都是基于共享内存的多处理器或流水(Pipeline)计算机上的,但由于多处理机中微处理器的个数非常有限且通过共享内存可同时传送和访问的数据也不可能很多。
MPI实现并行奇偶排序

MPI实现并⾏奇偶排序奇偶排序使⽤ MPI 实现奇偶排序算法,并且 MPI 进程只能向其相邻进程发送消息nprocs是进程数。
每个进程拥有独⽴的⼀块数据data[0 ~ block_len-1],组合起来为整个待排序的数组。
⽅法每个阶段排序之后不进⾏check此前,在每个阶段的奇偶排序进⾏完之后,都会进⾏⼀次进程之间的信息传递,以判断排序是否完成,这个过程要进⾏约3∗nprocs次的send/recv。
现在的优化是:总共只进⾏nprocs轮排序,不再进⾏check。
这样的话,即使是⽬前在最⼩编号进程中的元素,⽽它值较⼤,本应排序到最⼤编号进程中,也可以在nprocs轮中排到正确的位置。
这样之后,⼤约有⼏⼗ms的优化。
进程之间互相传递数据,然后进⾏优化后的归并在⼀个排序阶段中,相邻进程块互相发送⾃⼰的全部数据,之后在每个块内部将两个块的数据进⾏归并,但是只保留最⼩/最⼤的block_len 个元素,将其拷贝到⾃⼰的data上。
这样可以省掉⼀半的归并时间。
这样之后⼤约有100+ms的优化。
进程之间发送全部数据之前,先发送端点处的数据进程之间发送全部数据之前,先发送端点处的数据,判断左边进程中的最⼤元素是否⼩于等于右边进程中的最⼩元素,如果是,那么⽆需进⾏后续数据的发送和归并。
这样之后⼤约有⼏⼗ms的优化。
代码#include <algorithm>#include <cassert>#include <cstdio>#include <cstdlib>#include <mpi.h>#include <cmath>#include "worker.h"using namespace std;bool is_edge(int rank, bool odd_or_even, bool last_rank){if (odd_or_even == 0){return (rank & 1) == 0 && last_rank;}else{return rank == 0 || ((rank & 1) == 1 && last_rank);}}void merge_left(float *A, int nA, float *B, int nB, float *C){ //make sure C[nA-1] is availablefloat *p1 = A, *A_end = A + nA, *p2 = B, *B_end = B + nB, *p = C, *C_end = C + nA;while( p != C_end && p1 != A_end && p2 != B_end)*(p++) = ((*p1) <= (*p2)) ? *(p1++) : *(p2++);while( p != C_end )*(p++) = *(p1++);}void merge_right(float *A, int nA, float *B, int nB, float *C){float *p1 = A + nA , *p2 = B + nB , *p = C + nB;while( p != C && p1 != A && p2 != B )*(--p) = (*(p1-1) >= *(p2-1)) ? *(--p1) : *(--p2);while( p != C )*(--p) = *(--p2);}void Worker::sort() {//data[0, block_len)if (out_of_range) return ;std::sort(data, data + block_len);//先把当前进程数据排好序if (nprocs == 1) return ;bool odd_or_even = 0; // = 0: even; = 1: odd;float *cp_data = new float [block_len];float *adj_data = new float [ceiling(n, nprocs)];int limit = nprocs;while(limit--){if(is_edge(rank, odd_or_even, last_rank)){//边界情况,没有与其他进程存在于同⼀个进程块内}else if((rank & 1) == odd_or_even){ //receive infosize_t adj_block_len = std::min(block_len, n - (rank + 1) * block_len);MPI_Request request[2];MPI_Isend(data + block_len - 1, 1, MPI_FLOAT, rank + 1, 0, MPI_COMM_WORLD, &request[0]);MPI_Irecv(adj_data, 1, MPI_FLOAT, rank + 1, 1, MPI_COMM_WORLD, &request[1]);MPI_Wait(&request[0], MPI_STATUS_IGNORE);MPI_Wait(&request[1], MPI_STATUS_IGNORE); //发送端点数据if(data [block_len - 1] > adj_data[0]) {//此时两块之间存在未排好序的数据,需要排序MPI_Sendrecv(data, block_len, MPI_FLOAT, rank + 1, 0,adj_data, adj_block_len, MPI_FLOAT, rank + 1, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); //互相交换数据// mergemerge_left(data, (int)block_len, adj_data, (int)adj_block_len, cp_data);//进⾏归并排序,取前block_len个数据返回到cp_data中memcpy(data, cp_data, block_len * sizeof(float)); //拷贝回data}}else if ((rank & 1) == !odd_or_even){ //send infosize_t adj_block_len = ceiling(n, nprocs);MPI_Request request[2];MPI_Isend(data, 1, MPI_FLOAT, rank - 1, 1, MPI_COMM_WORLD, &request[1]);MPI_Irecv(adj_data + adj_block_len - 1, 1, MPI_FLOAT, rank- 1, 0, MPI_COMM_WORLD, &request[0]);MPI_Wait(&request[1], MPI_STATUS_IGNORE);MPI_Wait(&request[0], MPI_STATUS_IGNORE);//发送端点数据if (adj_data[adj_block_len - 1] > data[0]){//此时两块之间存在未排好序的数据,需要排序MPI_Sendrecv(data, block_len, MPI_FLOAT, rank - 1, 1,adj_data, adj_block_len, MPI_FLOAT, rank - 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); //互相交换数据// mergemerge_right(adj_data, (int)adj_block_len, data, (int)block_len, cp_data);//进⾏归并排序,取前block_len个数据返回到cp_data中memcpy(data, cp_data, block_len * sizeof(float)); //拷贝回data}}odd_or_even ^= 1;}delete[] cp_data;delete[] adj_data;}实验数据n N× P耗时(ms)相对单进程的加速⽐1000000001×112728.32600011000000001×26754.229000 1.8841000000001×43559.514000 3.5761000000001×82007.818000 6.3391000000001×161340.7710009.4931000000002×16870.30200014.625Processing math: 100%。
MPI并行编程

把每一个A(i)赋给B(i)
h= 1 to 2 h=1 I=1 to 2 (4/2**1) B(1)B(1)+B(2) B(2)B(3)+B(4) 若有2**2=4个处理器,则在1(h)级可能的并行 h=2 I=1 to 1 (4/2**2) 运算数目为4/2**1=2.则运算任务分摊给前两个 B(1)B(1)+B(2) 处理器 SB(1)
考虑一个用C语言声明的由N个复数组成的数组 double A[100] 假定进程P要把这个数组发送给进程Q:
1 MPI中的消息
要发送的消息 (1) 发送整个数 组A (2) 发送数组A 的头两个元素, 即: A[0]和A[1] (3) 发送数组 A 中所有偶数编 号的元素, 即: A[0],A[2],A[4], ... 可用的消息传递系统 理论的消息传递 send A to Q 商用的消息传递 (假定在一台计算机上, 一个双精度数是 64 位, 即 8 个字节.) send(A, 16, Q, tag) MPI 的消息传递 double A[100]; MPI_Data_type EvenElements; ... ... MPI_Type_vector (50, 1, 2, MPI_DOUBLE, &EvenElements); MPI_Type_commit (&EvenElements); MPI_Send (A, 1 , EvenElements, destination, ...); 说 明
open MP计算PI&MPI快速排序

–用MPI_Comm_rank获得进程的一个叫rank的值,该rank值为0到p-1间的整数,相当于进程的ID
intMPI_Comm_rank(MPI_Commcomm,int*rank);
3、最基本的MPI
MPI调用借口的总数虽然庞大,但根据实际编写MPI的经验,常用的MPI调用的个数确实有限。下面是6个最基本的MPI函数。
1.MPI_Init(…);
2.MPI_Comm_size(…);
3.MPI_Comm_rank(…);
4.MPI_Send(…);
5.MPI_Recv(…);
6.MPI_Finalize();
(四)、MPI消息
•MPI消息包括信封和数据两个部分,信封指出了发送或接收消息的对象及相关信息,而数据是本消息将要传递的内容
•Communicator:缺省MPI_COMM_WORLD
•Group:有限/N,有序/Rank [0,1,2,…N-1]
•Contex:Super_tag,用于标识该通讯空间.
(五)、阻塞与非阻塞
•用户发送缓冲区的重用:
–非阻塞的发送:仅当调用了有关结束该发送的语句后才能重用发送缓冲区,否则将导致错误;对于接收方,与此相同,仅当确认该接收请求已完成后才能使用。所以对于非阻塞操作,要先调用等待MPI_Wait()或测试MPI_Test()函数来结束或判断该请求,然后再向缓冲区中写入新内容或读取新内容。
PI的计算方法:
利用: 来计算PI的值。
三、实验过程和结果
程序代码:
// PI.cpp :定义控制台应用程序的入口点。
//
#include "stdafx.h"
MPI并行编程入门

S SISD
S I
MISD
M 指令个数
SMP- Symmetric MultiProcessing
多个CPU连接于统一的内存总线 内存地址统一编址,单一操作系统映像 可扩展性较差,一般CPU个数少于32个 目前商用服务器多采用这种架构
聚集方式:
归约
扫描
通信模式
一对一:点到点(point to point) 一对多:广播(broadcast),播撒(scatter) 多对一:收集(gather), 归约(reduce) 多对多:全交换(Tatal Exchange), 扫描(scan) , 置
换/移位(permutation/shift)
Work Pool
P1
P2
并行算法
• 并行算法设计基本原则
– 与体系结构相结合——线性结构,二维网络结 构……
– 具有可扩展性——并行算法是否随处理机个数 增加而能够线性或近似线性的加速
– 粗粒度——通常情况,粒度越大越好 – 减少通信——减少通信量和通信次数 – 优化性能——单机计算效率和并行效率
流水线计算示意图
并行化分解方法
– 分而治之方法:
• 以一个简单的求和问题为例,说明什么是分而治之方法。假设在q = 2*2*2个处理机上计算:
可以将计算依次分解为两个小的求和问题,用下图简单的描述(图中给出 的是处理机号)。在图中,从上至下是分解的过程,从下至上是求部分 和的过程。这就是有分有治的一个简单过程,也既是一种分而治之方法。
sp (q) q
–
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
MPI并行编程系列二快速排序阅读:63评论:0作者:飞得更高发表于2010-04-06 09:00原文链接在上一篇中对枚举排序的MPI并行算法进行了详细的描述和实现,算法相对简单,采用了并行编程模式中的单程序多数据流的并行编程模式。
在本篇中,将对快速排序进行并行化分析和实现。
本篇代码用到了上篇中的几个公用方法,在本篇中将不再做说明。
在本篇中,我们首先对快速排序算法进行描述和实现,并在此基础上分析此算法的并行性,确定并行编程模式,最后给出该算法的MPI实现。
一、快速排序算法说明快速排序时一种最基本的排序算法,效率相对较高。
其基本思想是:在当前无序数组R[1,n]中选取一个记录作为比较的"基准",即作为排序中的"轴"。
经过一趟排序后,当前无序数组R[1,n]就会以这个轴为核心划分为两个无序的子区r1[1,i-1],r2[i,n]。
其中左边的无序子区都会比"轴"小,右边的无序子区都会比"轴"大。
这样下一趟排序,我们就可以对这两个子区用同样的方法进行划分排序,知道所有的无序子区中的记录均排好为止。
根据算法的说明,快速排序时一个典型的递归算法,算法描述如下:无序数组R[1],R[2],.,R[n]quick_sort(R,start,end)if(start end)r=partion(R,start,end)quick_sort(R,start,r-1)quick_sort(R,r+1,end)endif end quick_sort方法partion的作用就是选取"轴",并将数组分为两个无序子区,并将该"轴"的最终位置返回,在这里我们选择数组的第一个元素为"轴",其算法描述为:partion(R,start,end)r=R[start]while(start end)while((R[end]=r)&&(start end))end--end ehile R[start]=R[end]while((R[start]r)&&(start end))start++end wile R[end]=R[start]end while R[start]=r return start end partion该排序算法的性能好坏主要取决于"轴"的选定,即无序数组的划分是否均衡。
最好的情况下,无序数组每次都会被划为两个均等的无序子区,这是算法的负责度为o(nlogn);最坏的情况,无序数组每次划分都是左边n-1个元素,右边0个元素,这时算法的复杂度为o(n^2)。
在通常的情况下,该算法的复杂度会依然保持在o(nlogn),上只不过具有更高的常数因子。
因此,选定一个有效地"轴",成为该算法的关键。
一般情况下,会选定无序数组的第一个,中间或者是最后一个元素作为算法的"轴",我们可以对着三个元素进行比较,取大小居中的那个元素作为该算法的"轴"。
二、快速排序算法的串行实现快速排序很明显的是一个递归的程序。
编写递归程序一个很重的要点就是确定在什么条件下终止递归操作。
主函数代码如下:1:void quick_sort_function(int*array,int start,int last){2:3:int part_position;4:5:if(start=last)6:return;7:8:part_position=part_array_head(array,start,last);9:quick_sort_function(array,start,part_position-1);10:quick_sort_function(array,part_position+1,last);11:}主函数代码很简单,一个终止递归的条件,一个递归方式。
在主函数中,核心函数为part_array_head,其代码如下:1:int part_array_head(int*array,int start,int last){2:3:int position_value=array[start];4:5:while(start last){6:while(startlast&&array[last]=position_value)7:last--;8:array[start]=array[last];9:10:while(startlast&&array[start]=position_value)11:start++;12:array[last]=array[start];13:}14:15:array[start]=position_value;16:17:return start;18:}从代码可以看出,快速排序的代码相对姜丹,总共不过三十行代码。
本人是非常喜欢递归操作的。
下面我们将对快速排序进行并行化分析。
三、快速排序并行化分析在并行编程策略中,有一种策略非常适合递归算法,自然也就成为我们快速排序并行化的首选策略。
这种策略为"分治策略",这种策略的核心思想就是将一个大而复杂的问题分解成若干个子问题分而治之。
若分解后的子问题依然过大或者是过于复杂,则可反复利用分治策略,直到很容易的求解子问题未知。
有此看出,分治策略也符合递归的思想。
要实现分治策略,主要分为三步:1、将大问题分解成小问题;2、求解小问题;3、归并小问题的解,得到最终结果。
其中各个小问题的求解就是我们并行化的所在。
分治策略的说明图如下:在快速排序算法中,我们就是将原无序数组按照一定得规则拆分成一个个子数组,即上图中的"分解"过程,每个子数组的排序可并行执行。
当各子数组排序完毕后,依此将结构传给其父数组,得到最终的结果,即上图中的"归并"过程。
基于以上的分析,我们给出快速排序算法MPI的实现如下:四、快速排序的MPI并行实现因为分治策略的特殊性,我们进行快速排序算法的进程数目为2^m个。
我们依然用进程p0来读取原数组,最终的排序结果也会由进程p0打印出来。
在该算法中,我们如果知道进程数目为2^m个,就应该能够求出m。
因此我写了一个实现函数,求一个整数的以2为底的对数的算法。
该算法的具体实现为:1:int log_int(int root,int num){2:3:int i,j;4:5:i=1;6:j=root;7:8:while(j num){9:j*=root;10:i++;11:}12:13:if(j num)14:i--;15:16:return i;17:}该并行算法的主函数为:1:void quick_sort_mpi(int*argv,char*argc){2:3:intprocess_id;4:int process_size;5:6:int*init_array;7:intarray_length;8:9:int log_num;10:int k;11:12:mpi_start(argv,argc,&process_size,&process_id,MPI_COMM_WORLD);13:14:if(process_size%2!=0){15:if(!process_id)16:printf("the sizeof the process must is the multipe of 2");17:18:MPI_Abort(MPI_COMM_WORLD,PROCESS_SIZE_ERROR);19:}20:21:log_num=log_int(2,process_size);22:array_length=ARRAY_LENGTH;23:24:if(!process_id){25:init_array=(int*)my_mpi_malloc(0,sizeof(int)*array_length);26:array_builder(init_array,array_length);27:array_int_print(array_length,init_array);28:}29:30://对数组进行快速排序31:quick_sort_mpi_function(init_array,array_length,log_num,process_id,0 ,MPI_COMM_WORLD);32:33:if(!process_id)34:array_int_print(array_length,init_array);35:36:MPI_Finalize();37:}在程序中出现的子函数在这里就不一一介绍了,其中主要的函数在上一篇枚举排序的MPI算法中都有所介绍。
主函数的核心就是quic_sort_mpi_fuction函数,该函数真正实现了快速排序,其代码如下:1:void quick_sort_mpi_function(2:int*init_array,//待排序数组3:int array_length,//待排序数组长度4:int log_num,//进程数取2为底的对数5:int process_id,//当前活动进程ID 6:int part_process_id,//对数组进行拆分的进程ID 7:MPI_Comm comm){8:9:int*local_array;10:int local_array_length=0;11:12:int send_array_length;13:14:int partion_position;15:16://取得要接收数据的进程号的进程号17:int receive_process_id;18:int j;19:20:MPI_Status status;21:22:if(log_num==0){23:if(process_id==part_process_id&&array_length1)24:quick_sort_function(init_array,0,array_length-1);25:26:return;27:}28:29:receive_process_id=part_process_id+pow_int(2,log_num-1);30:31://当活动进程为数组拆分进程时,按照快速排序方法对数组分成两部分32:if(process_id==part_process_id){33:partion_position=part_array_head(init_array,0,array_length-1);34:send_array_length=array_length-partion_position-1;35:local_array_length=partion_position;36:37:MPI_Send((void*)&send_array_length,1,MPI_INT,38:receive_process_id,LENGTH_MESSAGE,comm);39:40:if(send_array_length 0)41:MPI_Send((void*)(init_array+partion_position+1),send_array_length,42:MPI_INT,receive_process_id,DATA_MESSAGE,comm);43:}44:45://当活动进程为待接收数据的进程时,接收从拆分进程发送过来的数据46:if(process_id==receive_process_id){47:48:MPI_Recv((void*)&local_array_length,1,MPI_INT,part_process_id,49:LENGTH_MESSAGE,comm,&status);50:51:if(local_array_length 0)52:{53:local_array=(int*)my_mpi_malloc(process_id,sizeof(int)*local_array_l ength);54:MPI_Recv((void*)local_array,local_array_length,MPI_INT,part_process_ id,55:DATA_MESSAGE,comm,&status);56:57:}58:}59:60:j=local_array_length;61:MPI_Bcast(&j,1,MPI_INT,part_process_id,comm);62:if(j 1){64:quick_sort_mpi_function(init_array,local_array_length,log_num-1,65:process_id,part_process_id,comm);66:}67:68:j=local_array_length;69:MPI_Bcast(&j,1,MPI_INT,receive_process_id,MPI_COMM_WORLD);70:if(j 1)71:quick_sort_mpi_function(local_array,local_array_length,log_num-1,72:process_id,receive_process_id,comm);73:74:if(process_id==receive_process_id&&local_array_length 0)75:MPI_Send((void*)local_array,local_array_length,MPI_INT,76:part_process_id,DATA_MESSAGE_SORT,MPI_COMM_WORLD);77:78:if(process_id==part_process_id&&send_array_length 0)79:MPI_Recv((void*)(init_array+partion_position+1),send_array_length,80:MPI_INT,receive_process_id,DATA_MESSAGE_SORT,MPI_COMM_WORLD,&status);81:}该算法基本继承了并行编程策略的分治所发思想:分解---求解---归并。