ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/loops/BoxedLongSort.java
(Generate patch)

Comparing jsr166/src/test/loops/BoxedLongSort.java (file contents):
Revision 1.1 by dl, Sun Sep 19 12:55:36 2010 UTC vs.
Revision 1.11 by jsr166, Thu Jan 15 18:34:18 2015 UTC

# Line 1 | Line 1
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/licenses/publicdomain
4 > * http://creativecommons.org/publicdomain/zero/1.0/
5   */
6  
7 import java.util.concurrent.*;
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 boolean warmup = true;
14 >    //    static final int THRESHOLD = 64;
15  
16 <    public static void main (String[] args) throws Exception {
16 >    public static void main(String[] args) throws Exception {
17          int procs = 0;
18          int n = 1 << 22;
19          int reps = 20;
# Line 30 | Line 30 | class BoxedLongSort {
30              System.out.println("Usage: java BoxedLongSort threads n reps");
31              return;
32          }
33 <        ForkJoinPool pool = procs == 0? new ForkJoinPool() :
34 <            new ForkJoinPool(procs);
35 <        
36 <        Long[] a = new Long[n];
37 <        seqRandomFill(a, 0, n);
38 <
39 <        if (warmup) {
40 <            System.out.printf("Sorting %d longs, %d replications\n", n, 1);
41 <            Collections.shuffle(Arrays.asList(a));
42 <            long last = System.nanoTime();
43 <            java.util.Arrays.sort(a);
44 <            double elapsed = (double)(System.nanoTime() - last) / NPS;
45 <            System.out.printf("Arrays.sort   time:  %7.3f\n", elapsed);
46 <            checkSorted(a);
47 <        }
33 >        if (procs == 0)
34 >            procs = Runtime.getRuntime().availableProcessors();
35  
36 <        // for now hardwire 8 * #CPUs leaf tasks
37 <        THRESHOLD = 1 + ((n + 7) >>> 3) / pool.getParallelism();
38 <        //        THRESHOLD = 1 + ((n + 15) >>> 4) / pool.getParallelism();
39 <        //        THRESHOLD = 1 + ((n + 31) >>> 5) / pool.getParallelism();
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 <            Collections.shuffle(Arrays.asList(a));
64 <            //            pool.invoke(new RandomFiller(a, 0, n));
63 >            pool.invoke(new RandomRepacker(numbers, a, 0, n, n));
64 >            //            pool.invoke(new TaskChecker());
65              long last = System.nanoTime();
66 <            pool.invoke(new Sorter(a, new Long[n], 0, n));
67 <            double elapsed = (double)(System.nanoTime() - last) / NPS;
68 <            System.out.printf("Parallel sort time: %7.3f\n", elapsed);
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 <        System.out.println(pool);
76 >    }
77  
78 <        System.out.printf("Sorting %d longs, %d replications\n", n, sreps);
79 <        for (int i = 0; i < sreps; ++i) {
80 <            Collections.shuffle(Arrays.asList(a));
81 <            //            pool.invoke(new RandomFiller(a, 0, n));
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 <            java.util.Arrays.sort(a);
89 <            double elapsed = (double)(System.nanoTime() - last) / NPS;
90 <            System.out.printf("Arrays.sort   time:  %7.3f\n", elapsed);
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          }
78        System.out.println(pool);
79        pool.shutdown();
98      }
99  
100      static final class Sorter extends RecursiveAction {
101 <        final Long[] a;
101 >        final Long[] a;
102          final Long[] w;
103 <        final int origin;
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()  {
109 >        public void compute() {
110              int l = origin;
111 <            if (n <= THRESHOLD)
112 <                Arrays.sort(a, l, l+n);
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;
# Line 111 | Line 131 | class BoxedLongSort {
131              }
132          }
133      }
134 <    
134 >
135      static final class SubSorter extends RecursiveAction {
136          final Sorter left;
137          final Sorter right;
# Line 145 | Line 165 | class BoxedLongSort {
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.
148         *
168           */
169          public final void compute() {
170              Merger rights = null;
171 <            int nleft = ln;
172 <            int nright = rn;
173 <            while (nleft > THRESHOLD) { //  && nright > (THRESHOLD >>> 3)) {
174 <                int lh = nleft >>> 1;
175 <                int splitIndex = lo + lh;
176 <                Long split = a[splitIndex];
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 = nright;
184 >                int rh = rn;
185                  while (rl < rh) {
186 <                    int mid = (rl + rh) >>> 1;
187 <                    if (split <= a[ro + mid])
188 <                        rh = mid;
186 >                    int rm = (rl + rh) >>> 1;
187 >                    if (ls <= a[r + rm].longValue())
188 >                        rh = rm;
189                      else
190 <                        rl = mid + 1;
190 >                        rl = rm + 1;
191                  }
192 <                (rights = new Merger(a, w, splitIndex, nleft-lh, ro+rh,
193 <                                     nright-rh, wo+lh+rh, rights)).fork();
194 <                nleft = lh;
195 <                nright = rh;
196 <            }
197 <            
198 <            merge(nleft, nright);
199 <            if (rights != null)
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 <            
220 >
221          }
222  
223          final void merge(int nleft, int nright) {
# Line 206 | Line 250 | class BoxedLongSort {
250  
251      }
252  
253 <    static void checkSorted (Long[] a)  {
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 + ": " +
257 >                throw new Error("Unsorted at " + i + ": " +
258                                  a[i] + " / " + a[i+1]);
259              }
260          }
# Line 245 | Line 289 | class BoxedLongSort {
289          }
290      }
291  
292 +    static final class RandomRepacker extends RecursiveAction {
293 +        final Long[] src;
294 +        final Long[] dst;
295 +        final int lo, hi, size;
296 +        RandomRepacker(Long[] src, Long[] dst,
297 +                       int lo, int hi, int size) {
298 +            this.src = src; this.dst = dst;
299 +            this.lo = lo; this.hi = hi; this.size = size;
300 +        }
301 +
302 +        public final void compute() {
303 +            Long[] s = src;
304 +            Long[] d = dst;
305 +            int l = lo, h = hi, n = size;
306 +            if (h - l > THRESHOLD) {
307 +                int m = (l + h) >>> 1;
308 +                invokeAll(new RandomRepacker(s, d, l, m, n),
309 +                          new RandomRepacker(s, d, m, h, n));
310 +            }
311 +            else {
312 +                ThreadLocalRandom rng = ThreadLocalRandom.current();
313 +                for (int i = l; i < h; ++i)
314 +                    d[i] = s[rng.nextInt(n)];
315 +            }
316 +        }
317 +    }
318 +
319 +    static final int INSERTION_SORT_THRESHOLD = 8;
320 +
321 +    static void quickSort(Long[] a, int lo, int hi) {
322 +        for (;;) {
323 +            if (hi - lo <= INSERTION_SORT_THRESHOLD) {
324 +                for (int i = lo + 1; i <= hi; i++) {
325 +                    Long t = a[i];
326 +                    long tv = t.longValue();
327 +                    int j = i - 1;
328 +                    while (j >= lo && tv < a[j].longValue()) {
329 +                        a[j+1] = a[j];
330 +                        --j;
331 +                    }
332 +                    a[j+1] = t;
333 +                }
334 +                return;
335 +            }
336 +
337 +            int mid = (lo + hi) >>> 1;
338 +            if (a[lo].longValue() > a[mid].longValue()) {
339 +                Long t = a[lo]; a[lo] = a[mid]; a[mid] = t;
340 +            }
341 +            if (a[mid].longValue() > a[hi].longValue()) {
342 +                Long t = a[mid]; a[mid] = a[hi]; a[hi] = t;
343 +                if (a[lo].longValue() > a[mid].longValue()) {
344 +                    Long u = a[lo]; a[lo] = a[mid]; a[mid] = u;
345 +                }
346 +            }
347 +
348 +            long pivot = a[mid].longValue();
349 +            int left = lo+1;
350 +            int right = hi-1;
351 +            for (;;) {
352 +                while (pivot < a[right].longValue())
353 +                    --right;
354 +                while (left < right && pivot >= a[left].longValue())
355 +                    ++left;
356 +                if (left < right) {
357 +                    Long t = a[left]; a[left] = a[right]; a[right] = t;
358 +                    --right;
359 +                }
360 +                else break;
361 +            }
362 +
363 +            if (left - lo <= hi - right) {
364 +                quickSort(a, lo, left);
365 +                lo = left + 1;
366 +            }
367 +            else {
368 +                quickSort(a, right, hi);
369 +                hi = left;
370 +            }
371 +        }
372 +    }
373  
374   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines