-
Notifications
You must be signed in to change notification settings - Fork 0
/
quicksortC.c
184 lines (151 loc) · 4.89 KB
/
quicksortC.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "sorts.h"
#include "shared.h"
#ifdef SEQUENTIAL
#define cilk_spawn
#define cilk_syn
#else
// cilkplus libraries
#include <cilk/cilk.h>
#include <cilk/cilk_api.h>
#endif
#define UNIT (1000)
void quicksort(int a[], int n);
void quicksort2(int a[], int n, int * helperArray);
void _partition(int a[], int low, int high, struct partitionResult * result, int helperArray[], int pivotValue);
void writeBack(int helperArray[], int a[], int n, struct partitionResult * res1, struct partitionResult * res2, int isSmallerOne);
int already_set_worker_count = 0;
void setThreads(int threads) {
if (already_set_worker_count == 1) { return; }
char str[8];
sprintf(str, "%d", threads);
if (0!= __cilkrts_set_param("nworkers", str)) {
printf("Failed to set worker count. Aborting.\n");
exit(1);
}
already_set_worker_count = 1;
}
// --- --- ---- ---- ---- ---- ---- ---
// Implementation
// --- --- ---- ---- ---- ---- ---- ---
//maxThreads is not needed here, is just for omp implementation!
void quicksortC(int a[], int n, int maxThreads ) {
setThreads(maxThreads);
quicksort(a, n);
}
void quicksortC2(int a[], int n, int maxThreads ) {
setThreads(maxThreads);
int * helperArray = malloc(sizeof(int) * n);
quicksort2(a, n, helperArray);
free(helperArray);
}
void quicksort(int a[], int n)
{
//if we have just 1 element left return because there is nothing to do
if (n < 2) return;
//if we are lower than unit start sequential sort
if(n <= UNIT) {
quicksortS(a, 0, n-1);
return;
}
if (n<2) return;
int pivotIndex = randomNumberBetween(0, n-1);
int pivotValue = a[pivotIndex];
//switch pivot to first element
a[pivotIndex] = a[0];
a[0] = pivotValue;
struct partitionResult result;
partition(a, 1, n-1, &result, pivotValue);
int pi = result.smaller;
int aa;
aa = a[0]; a[0] = a[pi]; a[pi] = aa;
//spawn recursive cilk threads
cilk_spawn quicksort(a, pi);
cilk_spawn quicksort(a+pi+1, n-pi-1);
cilk_sync;
}
// --- --- ---- ---- ---- ---- ---- ---
// second version
// --- --- ---- ---- ---- ---- ---- ---
void quicksort2(int a[], int n, int * helperArray) {
//if we have just 1 element left return because there is nothing to do
if (n < 2) return;
//if we are lover than unit start sequential sort
if(n <= UNIT) {
quicksortS(a, 0, n-1);
return;
}
if(n < 10000) { // partition with just one thread
int pivotIndex = randomNumberBetween(0, n-1);
int pivotValue = a[pivotIndex];
//switch pivot to first element
a[pivotIndex] = a[0];
a[0] = pivotValue;
struct partitionResult result;
partition(a, 1, n-1, &result, pivotValue);
int pi = result.smaller;
int aa;
aa = a[0]; a[0] = a[pi]; a[pi] = aa;
//spawn recursive cilk threads
cilk_spawn quicksort2(a, pi, helperArray);
cilk_spawn quicksort2(a+pi+1, n-pi-1, helperArray+pi+1);
cilk_sync;
} else { // use more than one thread
struct partitionResult res1;
struct partitionResult res2;
int pivotIndex = randomNumberBetween(0, n-1);
int pivotValue = a[pivotIndex];
//switch pivot to first element
a[pivotIndex] = a[0];
a[0] = pivotValue;
//start by 1 cause a[0] contains pivotvalue
cilk_spawn _partition(a, 1, n/2, &res1, helperArray, pivotValue);
cilk_spawn _partition(a, n/2+1, n-1, &res2, helperArray, pivotValue);
cilk_sync;
cilk_spawn writeBack(helperArray, a, n, &res1, &res2, 1);
cilk_spawn writeBack(helperArray, a, n, &res1, &res2, 0);
cilk_sync;
int overallSmaller = res1.smaller + res2.smaller;
int overallLarger = res1.larger + res2.larger;
//write pivot on correct position
a[overallSmaller] = pivotValue;
cilk_spawn quicksort2(a, overallSmaller, helperArray);
cilk_spawn quicksort2(a+overallSmaller+1, overallLarger, helperArray+overallSmaller+1);
cilk_sync;
}
}
void _partition(int a[], int low, int high, struct partitionResult * result, int helperArray[], int pivotValue) {
partition(a, low, high, result, pivotValue);
memcpy(helperArray+low, a+low, (sizeof(int) * (high-low+1)));
}
void writeBack(int helperArray[],int a[], int n, struct partitionResult * res1, struct partitionResult * res2, int isSmallerOne) {
if(isSmallerOne == 1) {
//write smaller elements
int ai = 0;
//write smaller from 1st thread...
for (int i = 1; i <= res1->smaller; i++) {
a[ai] = helperArray[i];
ai++;
}
//write smaller from 2nd thread...
for(int i = n/2+1; i < n/2+1+res2->smaller; i++) {
a[ai] = helperArray[i];
ai++;
}
}else {
//write second part
int ai = res1->smaller + res2->smaller + 1;
//write larger from 1st thread...
for(int i = res1->smaller+1; i <= n/2; i++) {
a[ai] = helperArray[i];
ai++;
}
//write larger from 2nd thread...
for(int i = n/2+1+res2->smaller; i < n; i++) {
a[ai] = helperArray[i];
ai++;
}
}
}