ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/BoxedLongSort.java
Revision: 1.7
Committed: Mon Apr 9 13:18:06 2012 UTC (12 years, 1 month ago) by dl
Branch: MAIN
Changes since 1.6: +179 -52 lines
Log Message:
Add tests/demos for CountedCompleters

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.concurrent.*;
8 import java.util.*;
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 */
170 public final void compute() {
171 Merger rights = null;
172 Long[] a = this.a;
173 Long[] w = this.w;
174 int ln = this.ln;
175 int rn = this.rn;
176 int l = this.lo;
177 int r = this.ro;
178 int k = this.wo;
179 while (ln > THRESHOLD && rn > 4) {
180 int lh = ln >>> 1;
181 int lm = l + lh;
182 Long split = a[lm];
183 long ls = split.longValue();
184 int rl = 0;
185 int rh = rn;
186 while (rl < rh) {
187 int rm = (rl + rh) >>> 1;
188 if (ls <= a[r + rm].longValue())
189 rh = rm;
190 else
191 rl = rm + 1;
192 }
193 (rights = new Merger(a, w, lm, ln-lh, r+rh, rn-rh, k+lh+rh, rights)).fork();
194 rn = rh;
195 ln = lh;
196 }
197
198 int lFence = l + ln;
199 int rFence = r + rn;
200 for (Long t;;) {
201 if (l < lFence) {
202 Long al = a[l], ar;
203 if (r >= rFence ||
204 al.longValue() <= (ar = a[r]).longValue()) {
205 ++l; t = al;
206 }
207 else {
208 ++r; t = ar;
209 }
210 }
211 else if (r < rFence)
212 t = a[r++];
213 else
214 break;
215 w[k++] = t;
216 }
217
218 // merge(nleft, nright);
219 if (rights != null)
220 collectRights(rights);
221
222 }
223
224 final void merge(int nleft, int nright) {
225 int l = lo;
226 int lFence = lo + nleft;
227 int r = ro;
228 int rFence = ro + nright;
229 int k = wo;
230 while (l < lFence && r < rFence) {
231 Long al = a[l];
232 Long ar = a[r];
233 Long t;
234 if (al <= ar) { ++l; t = al; } else { ++r; t = ar; }
235 w[k++] = t;
236 }
237 while (l < lFence)
238 w[k++] = a[l++];
239 while (r < rFence)
240 w[k++] = a[r++];
241 }
242
243 static void collectRights(Merger rt) {
244 while (rt != null) {
245 Merger next = rt.next;
246 rt.next = null;
247 if (rt.tryUnfork()) rt.compute(); else rt.join();
248 rt = next;
249 }
250 }
251
252 }
253
254 static void checkSorted(Long[] a) {
255 int n = a.length;
256 for (int i = 0; i < n - 1; i++) {
257 if (a[i] > a[i+1]) {
258 throw new Error("Unsorted at " + i + ": " +
259 a[i] + " / " + a[i+1]);
260 }
261 }
262 }
263
264 static void seqRandomFill(Long[] array, int lo, int hi) {
265 ThreadLocalRandom rng = ThreadLocalRandom.current();
266 for (int i = lo; i < hi; ++i)
267 array[i] = rng.nextLong();
268 }
269
270 static final class RandomFiller extends RecursiveAction {
271 final Long[] array;
272 final int lo, hi;
273 RandomFiller(Long[] array, int lo, int hi) {
274 this.array = array; this.lo = lo; this.hi = hi;
275 }
276 public void compute() {
277 if (hi - lo <= THRESHOLD) {
278 Long[] a = array;
279 ThreadLocalRandom rng = ThreadLocalRandom.current();
280 for (int i = lo; i < hi; ++i)
281 a[i] = rng.nextLong();
282 }
283 else {
284 int mid = (lo + hi) >>> 1;
285 RandomFiller r = new RandomFiller(array, mid, hi);
286 r.fork();
287 (new RandomFiller(array, lo, mid)).compute();
288 r.join();
289 }
290 }
291 }
292
293
294 static final class RandomRepacker extends RecursiveAction {
295 final Long[] src;
296 final Long[] dst;
297 final int lo, hi, size;
298 RandomRepacker(Long[] src, Long[] dst,
299 int lo, int hi, int size) {
300 this.src = src; this.dst = dst;
301 this.lo = lo; this.hi = hi; this.size = size;
302 }
303
304 public final void compute() {
305 Long[] s = src;
306 Long[] d = dst;
307 int l = lo, h = hi, n = size;
308 if (h - l > THRESHOLD) {
309 int m = (l + h) >>> 1;
310 invokeAll(new RandomRepacker(s, d, l, m, n),
311 new RandomRepacker(s, d, m, h, n));
312 }
313 else {
314 ThreadLocalRandom rng = ThreadLocalRandom.current();
315 for (int i = l; i < h; ++i)
316 d[i] = s[rng.nextInt(n)];
317 }
318 }
319 }
320
321 static final int INSERTION_SORT_THRESHOLD = 8;
322
323 static void quickSort(Long[] a, int lo, int hi) {
324 for (;;) {
325 if (hi - lo <= INSERTION_SORT_THRESHOLD) {
326 for (int i = lo + 1; i <= hi; i++) {
327 Long t = a[i];
328 long tv = t.longValue();
329 int j = i - 1;
330 while (j >= lo && tv < a[j].longValue()) {
331 a[j+1] = a[j];
332 --j;
333 }
334 a[j+1] = t;
335 }
336 return;
337 }
338
339 int mid = (lo + hi) >>> 1;
340 if (a[lo].longValue() > a[mid].longValue()) {
341 Long t = a[lo]; a[lo] = a[mid]; a[mid] = t;
342 }
343 if (a[mid].longValue() > a[hi].longValue()) {
344 Long t = a[mid]; a[mid] = a[hi]; a[hi] = t;
345 if (a[lo].longValue() > a[mid].longValue()) {
346 Long u = a[lo]; a[lo] = a[mid]; a[mid] = u;
347 }
348 }
349
350 long pivot = a[mid].longValue();
351 int left = lo+1;
352 int right = hi-1;
353 for (;;) {
354 while (pivot < a[right].longValue())
355 --right;
356 while (left < right && pivot >= a[left].longValue())
357 ++left;
358 if (left < right) {
359 Long t = a[left]; a[left] = a[right]; a[right] = t;
360 --right;
361 }
362 else break;
363 }
364
365 if (left - lo <= hi - right) {
366 quickSort(a, lo, left);
367 lo = left + 1;
368 }
369 else {
370 quickSort(a, right, hi);
371 hi = left;
372 }
373 }
374 }
375
376 }