-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathodd-even-sort.c
107 lines (88 loc) · 3.32 KB
/
odd-even-sort.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
/**
* Compare and split operation to merge two sorted arrays.
*
* @param nlocal The number of elements in the local array.
* @param elmnts The local array of elements.
* @param relmnts The received array of elements to be merged with local elements.
* @param wspace Working space array to store the merged elements.
* @param keepsmall Flag indicating whether to keep the smaller elements (1) or larger elements (0).
*/
void compareSplit(int nlocal, int *elmnts, int *relmnts, int *wspace, int keepsmall) {
int i = 0, j = 0, k = 0;
// Merge elements from elmnts and relmnts into wspace based on the specified order
while (i < nlocal && j < nlocal) {
// Compare elements and choose the smaller or larger element based on keepsmall flag
if ((keepsmall && elmnts[i] < relmnts[j]) || (!keepsmall && elmnts[i] >= relmnts[j])) {
wspace[k++] = elmnts[i++];
} else {
wspace[k++] = relmnts[j++];
}
}
// Copy any remaining elements from elmnts
while (i < nlocal) {
wspace[k++] = elmnts[i++];
}
// Copy any remaining elements from relmnts
while (j < nlocal) {
wspace[k++] = relmnts[j++];
}
// Copy merged elements back to elmnts
for (i = 0; i < nlocal; i++) {
elmnts[i] = wspace[i];
}
}
int compare(const void *e1, const void *e2) {
return (*((int *)e1) - *((int *)e2));
}
int main(int argc, char *argv[]) {
int n, npes, myrank, nlocal, evenrank, oddrank, i;
int *elmnts, *relmnts, *wspace;
MPI_Status status;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &npes);
MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
if (argc != 2) {
if (myrank == 0) {
printf("Usage: %s <number_of_elements>\n", argv[0]);
}
MPI_Finalize();
return 1;
}
n = atoi(argv[1]);
nlocal = n / npes;
elmnts = (int *)malloc(nlocal * sizeof(int));
relmnts = (int *)malloc(nlocal * sizeof(int));
wspace = (int *)malloc(nlocal * sizeof(int));
srand(myrank);
for (i = 0; i < nlocal; i++)
elmnts[i] = rand();
qsort(elmnts, nlocal, sizeof(int), compare);
// Determine the rank of the processors that myrank needs to communicate during the odd and even phases of the algorithm
if (myrank % 2 == 0) {
oddrank = myrank - 1;
evenrank = myrank + 1;
} else {
oddrank = myrank + 1;
evenrank = myrank - 1;
}
// Set the ranks at the end of the linear process
if (oddrank < 0 || oddrank >= npes)
oddrank = MPI_PROC_NULL;
if (evenrank < 0 || evenrank >= npes)
evenrank = MPI_PROC_NULL;
for (i = 0; i < npes - 1; i++) {
if (i % 2 == 1) /* Odd phase */
MPI_Sendrecv(elmnts, nlocal, MPI_INT, oddrank, 1, relmnts, nlocal, MPI_INT, oddrank, 1, MPI_COMM_WORLD, &status);
else /* Even phase */
MPI_Sendrecv(elmnts, nlocal, MPI_INT, evenrank, 1, relmnts, nlocal, MPI_INT, evenrank, 1, MPI_COMM_WORLD, &status);
compareSplit(nlocal, elmnts, relmnts, wspace, myrank < status.MPI_SOURCE);
}
free(elmnts);
free(relmnts);
free(wspace);
MPI_Finalize();
return 0;
}