Skip to content

Commit 8f09c85

Browse files
committed
Improved a little bit radixSortImpl.
1 parent 675d57d commit 8f09c85

File tree

4 files changed

+96
-27
lines changed

4 files changed

+96
-27
lines changed

nb-configuration.xml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project-shared-configuration>
3+
<!--
4+
This file contains additional configuration written by modules in the NetBeans IDE.
5+
The configuration is intended to be shared among all the users of project and
6+
therefore it is assumed to be part of version control checkout.
7+
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
8+
-->
9+
<spellchecker-wordlist xmlns="http://www.netbeans.org/ns/spellchecker-wordlist/1">
10+
<word>multithreaded</word>
11+
</spellchecker-wordlist>
12+
</project-shared-configuration>

src/main/java/com/github/coderodde/util/ParallelRadixSort.java

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -356,19 +356,6 @@ private static void parallelRadixSortImpl(
356356
}
357357
}
358358

359-
// int[] testArray = source.clone();
360-
//
361-
// Arrays.sort(testArray);
362-
//
363-
// for (int i = 0; i != testArray.length; i++) {
364-
// int sourceElement = target[i];
365-
// int testElement = testArray[i];
366-
//
367-
// if (sourceElement != testElement) {
368-
// System.out.println("DEBUG: " + sourceElement + " vs. " + testElement + " at index " + i);
369-
// }
370-
// }
371-
372359
if (recursionDepth == DEEPEST_RECURSION_DEPTH) {
373360
// Nowhere to recur, all bytes are processed. Return.
374361
return;
@@ -411,22 +398,24 @@ private static void parallelRadixSortImpl(
411398
nonEmptyBucketIndices.shuffle(new Random());
412399

413400
// Distributed the buckets over sorter task lists:
414-
int f = 0;
415-
int j = 0;
401+
int frontIndex = 0;
402+
int cursorIndex = 0;
416403
int listIndex = 0;
417404
int optimalSubrangeLength = rangeLength / spawnDegree;
418405
int packed = 0;
419-
int sz = nonEmptyBucketIndices.size();
406+
int numberOfNonEmptyBuckets = nonEmptyBucketIndices.size();
420407

421-
while (j != sz) {
422-
int bucketKey = nonEmptyBucketIndices.getBucketKey(j++);
408+
while (cursorIndex != numberOfNonEmptyBuckets) {
409+
int bucketKey = nonEmptyBucketIndices.getBucketKey(cursorIndex++);
423410
int tmp = globalBucketSizeMap[bucketKey];
424411
packed += tmp;
425412

426-
if (packed >= optimalSubrangeLength || j == sz) {
413+
if (packed >= optimalSubrangeLength
414+
|| cursorIndex == numberOfNonEmptyBuckets) {
415+
427416
packed = 0;
428417

429-
for (int i = f; i != j; i++) {
418+
for (int i = frontIndex; i != cursorIndex; i++) {
430419
int bucketKey2 = nonEmptyBucketIndices.getBucketKey(i);
431420

432421
BucketKeyList bucketKeyList =
@@ -436,7 +425,7 @@ private static void parallelRadixSortImpl(
436425
}
437426

438427
listIndex++;
439-
f = j;
428+
frontIndex = cursorIndex;
440429
}
441430
}
442431

@@ -557,6 +546,8 @@ private static void radixSortImpl(int[] source,
557546
bucketSizeMap[bucketIndex]++;
558547
}
559548

549+
startIndexMap[0] = targetFromIndex;
550+
560551
// Compute starting indices for buckets in the target array. This is
561552
// actually just an accumulated array of bucketSizeMap, such that
562553
// startIndexMap[0] = 0, startIndexMap[1] = bucketSizeMap[0], ...,
@@ -571,7 +562,7 @@ private static void radixSortImpl(int[] source,
571562
int datum = source[i];
572563
int bucketKey = getBucketIndex(datum, recursionDepth);
573564

574-
target[targetFromIndex + startIndexMap[bucketKey] +
565+
target[/*targetFromIndex + */startIndexMap[bucketKey] +
575566
processedMap[bucketKey]++] = datum;
576567
}
577568

@@ -592,8 +583,8 @@ private static void radixSortImpl(int[] source,
592583
radixSortImpl(
593584
target,
594585
source,
595-
targetFromIndex + startIndexMap[i],
596-
sourceFromIndex + startIndexMap[i],
586+
startIndexMap[i],
587+
startIndexMap[i] - targetFromIndex + sourceFromIndex,
597588
bucketSizeMap[i],
598589
recursionDepth + 1);
599590
}

src/main/java/com/github/coderodde/util/ParallelRadixSortBenchmark.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
final class ParallelRadixSortBenchmark {
77

88
private static final int BENCHMARK_ITERATIONS = 20;
9-
private static final int MAXIMUM_ARRAY_SIZE = 50_000_000;
10-
private static final int MINIMUM_ARRAY_SIZE = 40_000_000;
9+
private static final int MAXIMUM_ARRAY_SIZE = 100_000_000;
10+
private static final int MINIMUM_ARRAY_SIZE = 90_000_000;
1111
private static final int MAXIMUM_FROM_INDEX = 1313;
1212
private static final int MAXIMUM_SKIP_LAST_ELEMENTS = 1711;
1313

@@ -25,6 +25,8 @@ private static void benchmark(boolean print) {
2525
long totalDuration2 = 0L;
2626

2727
for (int iteration = 0; iteration < BENCHMARK_ITERATIONS; iteration++) {
28+
System.gc();
29+
2830
int arrayLength =
2931
MINIMUM_ARRAY_SIZE +-
3032
random.nextInt(MAXIMUM_ARRAY_SIZE - MINIMUM_ARRAY_SIZE + 1);
@@ -56,7 +58,7 @@ private static void benchmark(boolean print) {
5658
+ duration1
5759
+ " ms, ParallelRadixSort.parallelSort: "
5860
+ duration2
59-
+ ", agreed: "
61+
+ " ms, agreed: "
6062
+ agreed);
6163
}
6264
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.github.coderodde.util;
2+
3+
import java.util.concurrent.Semaphore;
4+
5+
/**
6+
* This class provides the facilities for sorting and setting the thresholds in
7+
* multithreaded environments.
8+
*
9+
* @author Rodion "rodde" Efremov
10+
* @version 1.6 (Jun 30, 2023)
11+
*/
12+
public final class ThreadSafeWrapper {
13+
14+
private static final Semaphore MUTEX = new Semaphore(1, true);
15+
16+
public static void setInsertionsortThreshold(
17+
int newInsertionsortThreshold) {
18+
19+
MUTEX.acquireUninterruptibly();
20+
21+
ParallelRadixSort.setInsertionSortThreshold(
22+
newInsertionsortThreshold);
23+
24+
MUTEX.release();
25+
}
26+
27+
public static void setMergesortThreshold(
28+
int newMergesortThreshold) {
29+
30+
MUTEX.acquireUninterruptibly();
31+
32+
ParallelRadixSort.setMergesortThreshold(
33+
newMergesortThreshold);
34+
35+
MUTEX.release();
36+
}
37+
38+
public static void setThreadWorkloadThreshold(
39+
int newThreadWorkloadThreshold) {
40+
41+
MUTEX.acquireUninterruptibly();
42+
43+
ParallelRadixSort.setMinimumThreadWorkload(
44+
newThreadWorkloadThreshold);
45+
46+
MUTEX.release();
47+
}
48+
49+
public static void parallelSort(int[] array) {
50+
MUTEX.acquireUninterruptibly();
51+
52+
ParallelRadixSort.parallelSort(array);
53+
54+
MUTEX.release();
55+
}
56+
57+
public static void parallelSort(int[] array, int fromIndex, int toIndex) {
58+
MUTEX.acquireUninterruptibly();
59+
60+
ParallelRadixSort.parallelSort(array, fromIndex, toIndex);
61+
62+
MUTEX.release();
63+
}
64+
}

0 commit comments

Comments
 (0)