1
+ /*
2
+ * All rights reserved.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions are met:
6
+ *
7
+ * * Redistributions of source code must retain the above copyright notice,
8
+ * this list of conditions and the following disclaimer.
9
+ * * Redistributions in binary form must reproduce the above copyright notice,
10
+ * this list of conditions and the following disclaimer in the documentation
11
+ * and/or other materials provided with the distribution.
12
+ * * Neither the name of the author nor the names of its contributors may be
13
+ * used to endorse or promote products derived from this software without
14
+ * specific prior written permission.
15
+ *
16
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26
+ * POSSIBILITY OF SUCH DAMAGE.
27
+ *
28
+ */
29
+
30
+ #include "blocksort.h"
31
+
1
32
#include <fcntl.h>
2
33
#include <pthread.h>
3
34
#include <stdint.h>
6
37
#include <sys/time.h>
7
38
#include <unistd.h>
8
39
9
- typedef struct SortRecord {
10
- void * record ;
11
- uint64_t count ;
12
- } SortRecord_t ;
13
-
14
- void blocksort (SortRecord_t * data , int len );
40
+ void blocksort (SortElement_t * data , int len );
15
41
16
- #define swap (a , b ) \
17
- { \
18
- SortRecord_t _h = (a); \
19
- (a) = (b); \
20
- (b) = _h; \
42
+ #define swap (a , b ) \
43
+ { \
44
+ SortElement_t _h = (a); \
45
+ (a) = (b); \
46
+ (b) = _h; \
21
47
}
22
48
23
49
#define min (a , b ) ((a) < (b) ? (a) : (b))
@@ -28,7 +54,7 @@ void blocksort(SortRecord_t *data, int len);
28
54
if ((c).count < (b).count) { \
29
55
swap(a, c); \
30
56
} else { \
31
- SortRecord_t h = (a); \
57
+ SortElement_t h = (a); \
32
58
(a) = (b); \
33
59
(b) = (c); \
34
60
(c) = h; \
@@ -39,7 +65,7 @@ void blocksort(SortRecord_t *data, int len);
39
65
} else { \
40
66
if ((c).count < (b).count) { \
41
67
if ((c).count < (a).count) { \
42
- SortRecord_t h = (c); \
68
+ SortElement_t h = (c); \
43
69
(c) = (b); \
44
70
(b) = (a); \
45
71
(a) = h; \
@@ -54,27 +80,27 @@ static int n_threads;
54
80
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER ;
55
81
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER ;
56
82
57
- // static void init(SortRecord_t *data, int len);
83
+ // static void init(SortElement_t *data, int len);
58
84
59
- static void qusort (SortRecord_t * left , SortRecord_t * right );
85
+ static void qusort (SortElement_t * left , SortElement_t * right );
60
86
61
- static void insert_sort (SortRecord_t * left , SortRecord_t * right );
87
+ static void insert_sort (SortElement_t * left , SortElement_t * right );
62
88
63
- static void partition (SortRecord_t * left0 , SortRecord_t * right0 , SortRecord_t * * l1 , SortRecord_t * * r1 , SortRecord_t * * l2 , SortRecord_t * * r2 );
89
+ static void partition (SortElement_t * left0 , SortElement_t * right0 , SortElement_t * * l1 , SortElement_t * * r1 , SortElement_t * * l2 , SortElement_t * * r2 );
64
90
65
91
static void * sort_thr (void * arg );
66
92
67
- void insert_sort (SortRecord_t * left , SortRecord_t * right ) {
93
+ void insert_sort (SortElement_t * left , SortElement_t * right ) {
68
94
// put minimum to left position, so we can save
69
95
// one inner loop comparison for insert sort
70
- for (SortRecord_t * pi = left + 1 ; pi <= right ; pi ++ ) {
96
+ for (SortElement_t * pi = left + 1 ; pi <= right ; pi ++ ) {
71
97
if (pi -> count < left -> count ) {
72
98
swap (* pi , * left );
73
99
}
74
100
}
75
- for (SortRecord_t * pi = left + 2 ; pi <= right ; pi ++ ) {
76
- SortRecord_t h = * pi ;
77
- SortRecord_t * pj = pi - 1 ;
101
+ for (SortElement_t * pi = left + 2 ; pi <= right ; pi ++ ) {
102
+ SortElement_t h = * pi ;
103
+ SortElement_t * pj = pi - 1 ;
78
104
while (h .count < pj -> count ) {
79
105
* (pj + 1 ) = * pj ;
80
106
pj -= 1 ;
@@ -83,12 +109,12 @@ void insert_sort(SortRecord_t *left, SortRecord_t *right) {
83
109
}
84
110
}
85
111
86
- static void partition (SortRecord_t * left0 , SortRecord_t * right0 , SortRecord_t * * l1 , SortRecord_t * * r1 , SortRecord_t * * l2 , SortRecord_t * * r2 ) {
87
- SortRecord_t * left = left0 + 1 ;
88
- SortRecord_t * right = right0 ;
112
+ static void partition (SortElement_t * left0 , SortElement_t * right0 , SortElement_t * * l1 , SortElement_t * * r1 , SortElement_t * * l2 , SortElement_t * * r2 ) {
113
+ SortElement_t * left = left0 + 1 ;
114
+ SortElement_t * right = right0 ;
89
115
90
- SortRecord_t * mid = left0 + (right0 - left0 ) / 2 ;
91
- SortRecord_t piv = * mid ;
116
+ SortElement_t * mid = left0 + (right0 - left0 ) / 2 ;
117
+ SortElement_t piv = * mid ;
92
118
* mid = * left ;
93
119
sort3fast (* left0 , piv , * right0 );
94
120
* left = piv ;
@@ -117,85 +143,8 @@ static void partition(SortRecord_t *left0, SortRecord_t *right0, SortRecord_t **
117
143
}
118
144
}
119
145
120
- /*
121
- static void partition(SortRecord_t *left0, SortRecord_t *right0,
122
- SortRecord_t **l1, SortRecord_t **r1,
123
- SortRecord_t **l2, SortRecord_t **r2) {
124
-
125
- SortRecord_t *mid = left0 + (right0 - left0) / 2;
126
- SortRecord_t piv = *mid;
127
- *mid = *(left0 + 1);
128
- sort3fast(*left0, piv, *right0);
129
- *(left0 + 1) = piv;
130
-
131
- SortRecord_t *left, *right;
132
- #define BSZ 256
133
- if (right0 - left0 > 2 * BSZ + 3) {
134
-
135
- left = left0 + 2;
136
- right = right0 - 1;
137
- SortRecord_t *offl[BSZ];
138
- SortRecord_t *offr[BSZ];
139
- SortRecord_t **ol = offl;
140
- SortRecord_t **or = offr;
141
- do {
142
- if (ol == offl) {
143
- SortRecord_t *pd = left;
144
- do {
145
- *ol = pd;
146
- ol += (piv.count < pd->count);
147
- pd += 1;
148
- }
149
- while (pd < left + BSZ);
150
- }
151
- if (or == offr) {
152
- SortRecord_t* pd = right;
153
- do {
154
- *or = pd;
155
- or += (piv.count > pd->count);
156
- pd -= 1;
157
- }
158
- while (pd > right - BSZ);
159
- }
160
- int min = min(ol - offl, or - offr);
161
- ol -= min;
162
- or -= min;
163
- for (int i = 0; i < min; i++) {
164
- swap(**(ol + i), **(or + i));
165
- }
166
- if (ol == offl) left += BSZ;
167
- if (or == offr) right -= BSZ;
168
- }
169
- while (right - left > 2 * BSZ);
170
- left -= 1;
171
- right += 1;
172
- }
173
- else {
174
- left = left0 + 1;
175
- right = right0;
176
- }
177
- while (1) {
178
- do left += 1; while(left->count < piv.count);
179
- do right -= 1; while (right->count > piv.count);
180
- if (left >= right) break;
181
- swap(*left, *right);
182
- }
183
- *(left0 + 1) = *right;
184
- *right = piv;
185
-
186
- if (right < mid) {
187
- *l1 = left0; *r1 = right - 1;
188
- *l2 = right + 1; *r2 = right0;
189
- }
190
- else {
191
- *l1 = right + 1; *r1 = right0;
192
- *l2 = left0; *r2 = right - 1;
193
- }
194
- }
195
- */
196
-
197
146
static void * sort_thr (void * arg ) {
198
- SortRecord_t * * par = (SortRecord_t * * )arg ;
147
+ SortElement_t * * par = (SortElement_t * * )arg ;
199
148
qusort (par [0 ], par [1 ]);
200
149
free (arg );
201
150
pthread_mutex_lock (& mutex );
@@ -207,24 +156,24 @@ static void *sort_thr(void *arg) {
207
156
return NULL ;
208
157
}
209
158
210
- static void qusort_single (SortRecord_t * left , SortRecord_t * right ) {
211
- SortRecord_t * l , * r ;
159
+ static void qusort_single (SortElement_t * left , SortElement_t * right ) {
160
+ SortElement_t * l , * r ;
212
161
while (right - left >= 50 ) {
213
162
partition (left , right , & l , & r , & left , & right );
214
163
qusort (l , r );
215
164
}
216
165
insert_sort (left , right );
217
166
}
218
167
219
- static void qusort (SortRecord_t * left , SortRecord_t * right ) {
168
+ static void qusort (SortElement_t * left , SortElement_t * right ) {
220
169
while (right - left >= 50 ) {
221
- SortRecord_t * l , * r ;
170
+ SortElement_t * l , * r ;
222
171
partition (left , right , & l , & r , & left , & right );
223
172
224
173
if (right - left > 100000 && n_threads < max_threads ) {
225
174
// start a new thread - max_threads is a soft limit
226
175
pthread_t thread ;
227
- SortRecord_t * * param = (SortRecord_t * * )malloc (2 * sizeof (SortRecord_t * ));
176
+ SortElement_t * * param = (SortElement_t * * )malloc (2 * sizeof (SortElement_t * ));
228
177
if (!param ) abort ();
229
178
param [0 ] = left ;
230
179
param [1 ] = right ;
@@ -241,11 +190,11 @@ static void qusort(SortRecord_t *left, SortRecord_t *right) {
241
190
insert_sort (left , right );
242
191
}
243
192
244
- void blocksort (SortRecord_t * data , int len ) {
193
+ void blocksort (SortElement_t * data , int len ) {
245
194
// shortcut for few entries
246
195
if (len < 50 ) {
247
- SortRecord_t * left = data ;
248
- SortRecord_t * right = data + len - 1 ;
196
+ SortElement_t * left = data ;
197
+ SortElement_t * right = data + len - 1 ;
249
198
qusort_single (left , right );
250
199
return ;
251
200
}
@@ -257,7 +206,7 @@ void blocksort(SortRecord_t *data, int len) {
257
206
max_threads = 8 ;
258
207
259
208
pthread_t thread ;
260
- SortRecord_t * * param = (SortRecord_t * * )malloc (2 * sizeof (SortRecord_t * ));
209
+ SortElement_t * * param = (SortElement_t * * )malloc (2 * sizeof (SortElement_t * ));
261
210
if (!param ) abort ();
262
211
param [0 ] = data ;
263
212
param [1 ] = data + len - 1 ;
@@ -267,51 +216,5 @@ void blocksort(SortRecord_t *data, int len) {
267
216
n_threads ++ ;
268
217
while (n_threads > 0 ) pthread_cond_wait (& cond , & mutex );
269
218
pthread_mutex_unlock (& mutex );
270
- }
271
-
272
- /*
273
- static double t(void) {
274
-
275
- static double t0;
276
- struct timeval tv;
277
- gettimeofday(&tv, NULL);
278
- double h = t0;
279
- t0 = tv.tv_sec + tv.tv_usec / 1000000.0;
280
- return t0 - h;
281
- }
282
-
283
- static void init(SortRecord_t *data, int len) {
284
- for (int i = 0; i < len; i++) {
285
- data[i].count = rand();
286
- }
287
- }
288
219
289
- static void test(SortRecord_t *data, int len) {
290
- for (int i = 1; i < len; i++) {
291
- if (data[i].count < data[i - 1].count) {
292
- printf("ERROR\n");
293
- break;
294
- }
295
- }
296
- }
297
-
298
-
299
- int main(void) {
300
-
301
- size_t size = 50 * 1000000;
302
-
303
- SortRecord_t *data = malloc(size * sizeof(SortRecord_t));
304
- if ( !data ) {
305
- perror("malloc() failed: ");
306
- exit(255);
307
- }
308
- init(data, size);
309
- printf("Sorting %lu million numbers with Quicksort ...\n", size / 1000000);
310
- t();
311
-
312
- blocksort(data, size);
313
- printf("%.2fs\n", t());
314
- test(data, size);
315
- return 0;
316
- }
317
- */
220
+ } // End of blocksort
0 commit comments