ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/BoxedLongSort.java
Revision: 1.10
Committed: Wed Dec 31 17:00:58 2014 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.9: +1 -1 lines
Log Message:
lexicographic import order

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
6
7 import java.util.*;
8 import java.util.concurrent.*;
9
10 class BoxedLongSort {
11 static final long NPS = (1000L * 1000 * 1000);
12
13 static int THRESHOLD;
14 // static final int THRESHOLD = 64;
15
16 public static void main(String[] args) throws Exception {
17 int procs = 0;
18 int n = 1 << 22;
19 int reps = 20;
20 int sreps = 2;
21 try {
22 if (args.length > 0)
23 procs = Integer.parseInt(args[0]);
24 if (args.length > 1)
25 n = Integer.parseInt(args[1]);
26 if (args.length > 2)
27 reps = Integer.parseInt(args[1]);
28 }
29 catch (Exception e) {
30 System.out.println("Usage: java BoxedLongSort threads n reps");
31 return;
32 }
33 if (procs == 0)
34 procs = Runtime.getRuntime().availableProcessors();
35
36 THRESHOLD = ((n + 7) >>> 3) / procs;
37 // THRESHOLD = ((n + 15) >>> 4) / procs;
38 // THRESHOLD = ((n + 31) >>> 5) / procs;
39 if (THRESHOLD < 64)
40 THRESHOLD = 64;
41
42 System.out.println("Threshold = " + THRESHOLD);
43
44 Long[] numbers = new Long[n];
45 for (int i = 0; i < n; ++i)
46 numbers[i] = Long.valueOf(i);
47 Long[] a = new Long[n];
48 ForkJoinPool pool = new ForkJoinPool(procs);
49 seqTest(a, numbers, pool, 1);
50 System.out.println(pool);
51 parTest(a, numbers, pool, reps);
52 System.out.println(pool);
53 seqTest(a, numbers, pool, 2);
54 System.out.println(pool);
55 pool.shutdown();
56 }
57
58 static void seqTest(Long[] a, Long[] numbers, ForkJoinPool pool, int reps) {
59 int n = numbers.length;
60 System.out.printf("Sorting %d longs, %d replications\n", n, reps);
61 long start = System.nanoTime();
62 for (int i = 0; i < reps; ++i) {
63 pool.invoke(new RandomRepacker(numbers, a, 0, n, n));
64 // pool.invoke(new TaskChecker());
65 long last = System.nanoTime();
66 // quickSort(a, 0, n-1);
67 java.util.Arrays.sort(a);
68 long now = System.nanoTime();
69 double total = (double)(now - start) / NPS;
70 double elapsed = (double)(now - last) / NPS;
71 System.out.printf("Arrays.sort time: %7.3f total %9.3f\n",
72 elapsed, total);
73 if (i == 0)
74 checkSorted(a);
75 }
76 }
77
78 static void parTest(Long[] a, Long[] numbers, ForkJoinPool pool, int reps) {
79 int n = numbers.length;
80 Long[] w = new Long[n];
81 System.out.printf("Sorting %d longs, %d replications\n", n, reps);
82 long start = System.nanoTime();
83 for (int i = 0; i < reps; ++i) {
84 // Arrays.fill(w, 0, n, null);
85 pool.invoke(new RandomRepacker(numbers, a, 0, n, n));
86 // pool.invoke(new TaskChecker());
87 long last = System.nanoTime();
88 pool.invoke(new Sorter(a, w, 0, n));
89 long now = System.nanoTime();
90 // pool.invoke(new TaskChecker());
91 double total = (double)(now - start) / NPS;
92 double elapsed = (double)(now - last) / NPS;
93 System.out.printf("Parallel sort time: %7.3f total %9.3f\n",
94 elapsed, total);
95 if (i == 0)
96 checkSorted(a);
97 }
98 }
99
100 static final class Sorter extends RecursiveAction {
101 final Long[] a;
102 final Long[] w;
103 final int origin;
104 final int n;
105 Sorter(Long[] a, Long[] w, int origin, int n) {
106 this.a = a; this.w = w; this.origin = origin; this.n = n;
107 }
108
109 public void compute() {
110 int l = origin;
111 if (n <= THRESHOLD) {
112 // Arrays.sort(a, l, l+n);
113 quickSort(a, l, l+n-1);
114 }
115 else { // divide in quarters to ensure sorted array in a not w
116 int h = n >>> 1;
117 int q = n >>> 2;
118 int u = h + q;
119 SubSorter rs = new SubSorter
120 (new Sorter(a, w, l+h, q),
121 new Sorter(a, w, l+u, n-u),
122 new Merger(a, w, l+h, q, l+u, n-u, l+h, null));
123 rs.fork();
124 Sorter rl = new Sorter(a, w, l+q, h-q);
125 rl.fork();
126 (new Sorter(a, w, l, q)).compute();
127 rl.join();
128 (new Merger(a, w, l, q, l+q, h-q, l, null)).compute();
129 rs.join();
130 new Merger(w, a, l, h, l+h, n-h, l, null).compute();
131 }
132 }
133 }
134
135 static final class SubSorter extends RecursiveAction {
136 final Sorter left;
137 final Sorter right;
138 final Merger merger;
139 SubSorter(Sorter left, Sorter right, Merger merger) {
140 this.left = left; this.right = right; this.merger = merger;
141 }
142 public void compute() {
143 right.fork();
144 left.compute();
145 right.join();
146 merger.compute();
147 }
148 }
149
150 static final class Merger extends RecursiveAction {
151 final Long[] a; final Long[] w;
152 final int lo; final int ln; final int ro; final int rn; final int wo;
153 Merger next;
154 Merger(Long[] a, Long[] w, int lo, int ln, int ro, int rn, int wo,
155 Merger next) {
156 this.a = a; this.w = w;
157 this.lo = lo; this.ln = ln;
158 this.ro = ro; this.rn = rn;
159 this.wo = wo;
160 this.next = next;
161 }
162
163 /**
164 * Merge left and right by splitting left in half,
165 * and finding index of right closest to split point.
166 * Uses left-spine decomposition to generate all
167 * merge tasks before bottomming out at base case.
168 */
169 public final void compute() {
170 Merger rights = null;
171 Long[] a = this.a;
172 Long[] w = this.w;
173 int ln = this.ln;
174 int rn = this.rn;
175 int l = this.lo;
176 int r = this.ro;
177 int k = this.wo;
178 while (ln > THRESHOLD && rn > 4) {
179 int lh = ln >>> 1;
180 int lm = l + lh;
181 Long split = a[lm];
182 long ls = split.longValue();
183 int rl = 0;
184 int rh = rn;
185 while (rl < rh) {
186 int rm = (rl + rh) >>> 1;
187 if (ls <= a[r + rm].longValue())
188 rh = rm;
189 else
190 rl = rm + 1;
191 }
192 (rights = new Merger(a, w, lm, ln-lh, r+rh, rn-rh, k+lh+rh, rights)).fork();
193 rn = rh;
194 ln = lh;
195 }
196
197 int lFence = l + ln;
198 int rFence = r + rn;
199 for (Long t;;) {
200 if (l < lFence) {
201 Long al = a[l], ar;
202 if (r >= rFence ||
203 al.longValue() <= (ar = a[r]).longValue()) {
204 ++l; t = al;
205 }
206 else {
207 ++r; t = ar;
208 }
209 }
210 else if (r < rFence)
211 t = a[r++];
212 else
213 break;
214 w[k++] = t;
215 }
216
217 // merge(nleft, nright);
218 if (rights != null)
219 collectRights(rights);
220
221 }
222
223 final void merge(int nleft, int nright) {
224 int l = lo;
225 int lFence = lo + nleft;
226 int r = ro;
227 int rFence = ro + nright;
228 int k = wo;
229 while (l < lFence && r < rFence) {
230 Long al = a[l];
231 Long ar = a[r];
232 Long t;
233 if (al <= ar) { ++l; t = al; } else { ++r; t = ar; }
234 w[k++] = t;
235 }
236 while (l < lFence)
237 w[k++] = a[l++];
238 while (r < rFence)
239 w[k++] = a[r++];
240 }
241
242 static void collectRights(Merger rt) {
243 while (rt != null) {
244 Merger next = rt.next;
245 rt.next = null;
246 if (rt.tryUnfork()) rt.compute(); else rt.join();
247 rt = next;
248 }
249 }
250
251 }
252
253 static void checkSorted(Long[] a) {
254 int n = a.length;
255 for (int i = 0; i < n - 1; i++) {
256 if (a[i] > a[i+1]) {
257 throw new Error("Unsorted at " + i + ": " +
258 a[i] + " / " + a[i+1]);
259 }
260 }
261 }
262
263 static void seqRandomFill(Long[] array, int lo, int hi) {
264 ThreadLocalRandom rng = ThreadLocalRandom.current();
265 for (int i = lo; i < hi; ++i)
266 array[i] = rng.nextLong();
267 }
268
269 static final class RandomFiller extends RecursiveAction {
270 final Long[] array;
271 final int lo, hi;
272 RandomFiller(Long[] array, int lo, int hi) {
273 this.array = array; this.lo = lo; this.hi = hi;
274 }
275 public void compute() {
276 if (hi - lo <= THRESHOLD) {
277 Long[] a = array;
278 ThreadLocalRandom rng = ThreadLocalRandom.current();
279 for (int i = lo; i < hi; ++i)
280 a[i] = rng.nextLong();
281 }
282 else {
283 int mid = (lo + hi) >>> 1;
284 RandomFiller r = new RandomFiller(array, mid, hi);
285 r.fork();
286 (new RandomFiller(array, lo, mid)).compute();
287 r.join();
288 }
289 }
290 }
291
292
293 static final class RandomRepacker extends RecursiveAction {
294 final Long[] src;
295 final Long[] dst;
296 final int lo, hi, size;
297 RandomRepacker(Long[] src, Long[] dst,
298 int lo, int hi, int size) {
299 this.src = src; this.dst = dst;
300 this.lo = lo; this.hi = hi; this.size = size;
301 }
302
303 public final void compute() {
304 Long[] s = src;
305 Long[] d = dst;
306 int l = lo, h = hi, n = size;
307 if (h - l > THRESHOLD) {
308 int m = (l + h) >>> 1;
309 invokeAll(new RandomRepacker(s, d, l, m, n),
310 new RandomRepacker(s, d, m, h, n));
311 }
312 else {
313 ThreadLocalRandom rng = ThreadLocalRandom.current();
314 for (int i = l; i < h; ++i)
315 d[i] = s[rng.nextInt(n)];
316 }
317 }
318 }
319
320 static final int INSERTION_SORT_THRESHOLD = 8;
321
322 static void quickSort(Long[] a, int lo, int hi) {
323 for (;;) {
324 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
325 for (int i = lo + 1; i <= hi; i++) {
326 Long t = a[i];
327 long tv = t.longValue();
328 int j = i - 1;
329 while (j >= lo && tv < a[j].longValue()) {
330 a[j+1] = a[j];
331 --j;
332 }
333 a[j+1] = t;
334 }
335 return;
336 }
337
338 int mid = (lo + hi) >>> 1;
339 if (a[lo].longValue() > a[mid].longValue()) {
340 Long t = a[lo]; a[lo] = a[mid]; a[mid] = t;
341 }
342 if (a[mid].longValue() > a[hi].longValue()) {
343 Long t = a[mid]; a[mid] = a[hi]; a[hi] = t;
344 if (a[lo].longValue() > a[mid].longValue()) {
345 Long u = a[lo]; a[lo] = a[mid]; a[mid] = u;
346 }
347 }
348
349 long pivot = a[mid].longValue();
350 int left = lo+1;
351 int right = hi-1;
352 for (;;) {
353 while (pivot < a[right].longValue())
354 --right;
355 while (left < right && pivot >= a[left].longValue())
356 ++left;
357 if (left < right) {
358 Long t = a[left]; a[left] = a[right]; a[right] = t;
359 --right;
360 }
361 else break;
362 }
363
364 if (left - lo <= hi - right) {
365 quickSort(a, lo, left);
366 lo = left + 1;
367 }
368 else {
369 quickSort(a, right, hi);
370 hi = left;
371 }
372 }
373 }
374
375 }