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_length > 1)
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_length);
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: }
该算法基本继承了并行编程策略的分治所发思想:分解 --- 求解 --- 归并。
五、MPI函数的说明
在该算法中,用到了MPI两个重要的通信函数MPI_Send和MPI_Recv,发送和接受函数。这两个函数实现了两个进程间的通信。同时,这两个函数是阻塞通信函数,即:
进程在没有接受到或发送完数据的情况下,将阻塞。
这样我们就完成了快速排序算法并行化得描述和实现,在这两篇中,分别介绍了并行编程策略的两个策略:单程序多数据流策略和分治策略。下篇将介绍并行正则采样
排序算法的设计和实现。