Skip to content

Commit f68db69

Browse files
committed
add : Parallel Odd-Even Merge Sort
1 parent 46cba63 commit f68db69

File tree

8 files changed

+146
-17
lines changed

8 files changed

+146
-17
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ Algorithms covered so far:
201201
| [Cycle Sort](#cycle-sort) | CycleSort |
202202
| [Odd-Even Sort](#odd-even-sort) | OddEvenSort |
203203
| [Odd-Even Merge Sort](#odd-even-merge-sort) | OddEvenMergeSort |
204+
| [Odd-Even Merge Sort (parallel)](#odd-even-merge-sort) | ParallelOddEvenMergeSort |
204205

205206

206207
<br />
@@ -579,7 +580,7 @@ and depth
579580
<span> ![O((log_n)^2)](https://latex.codecogs.com/svg.image?O((\log&space;n)^2)) </span>
580581
where n is the number of items to be sorted.
581582

582-
\[todo] add parallel-ver.
583+
583584

584585

585586
<br />

glob_bench_test/sort_bench_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,16 @@ func BenchmarkOddEvenMergeSort(b *testing.B) {
364364
b.StopTimer()
365365
}
366366
}
367+
368+
func BenchmarkParallelOddEvenMergeSort(b *testing.B) {
369+
b.StopTimer()
370+
unsorted := sliceBuilder(lengthforbench)
371+
test := make([]int, len(unsorted))
372+
373+
for i := 0; i < b.N; i++ {
374+
copy(test, unsorted)
375+
b.StartTimer()
376+
sorts.ParallelOddEvenMergeSort(test)
377+
b.StopTimer()
378+
}
379+
}

glob_bench_test/sort_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,14 @@ func TestSort(t *testing.T) {
220220
if !reflect.DeepEqual(test, verify) {
221221
t.Error("Wrong result [odd-even sort]")
222222
}
223+
224+
test = make([]int, len(origin))
225+
copy(test, origin)
226+
t.Run("parallel odd-even merge sort", func(t *testing.T) { sorts.ParallelOddEvenMergeSort(test) })
227+
228+
if !reflect.DeepEqual(test, verify) {
229+
t.Error("Wrong result [parallel odd-even sort]")
230+
}
223231
size <<= 2
224232
}
225233
}

simplytest/base_sort_list.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ func CallOddEvenSort(origin []int, verify []int, callName string) OutputForm {
368368
func CallOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
369369
size := len(origin)
370370
if (size & (size - 1)) != 0 {
371-
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("top-down odd-even sort can't run"))
371+
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("odd-even sort can't run"))
372372
fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
373373
return OutputForm{false, callName, -1, false, ""}
374374
}
@@ -384,3 +384,23 @@ func CallOddEvenMergeSort(origin []int, verify []int, callName string) OutputFor
384384
}
385385
return OutputForm{false, callName, -1, false, ""}
386386
}
387+
388+
func CallParallelOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
389+
size := len(origin)
390+
if (size & (size - 1)) != 0 {
391+
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("parallel odd-even sort can't run"))
392+
fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
393+
return OutputForm{false, callName, -1, false, ""}
394+
}
395+
if PARALLEL_ODDEVEN_MERGE_SORT {
396+
test := make([]int, len(origin))
397+
copy(test, origin)
398+
fmt.Printf("runing %s...\n", callName)
399+
start := time.Now()
400+
sorts.ParallelOddEvenMergeSort(test)
401+
end := time.Since(start)
402+
eq, err := Equal(verify, test)
403+
return OutputForm{true, callName, end.Nanoseconds(), eq, err}
404+
}
405+
return OutputForm{false, callName, -1, false, ""}
406+
}

simplytest/option.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const (
3838
CYCLE_SORT Activate = true
3939
ODDEVEN_SORT Activate = true
4040
ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
41+
PARALLEL_ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
4142
)
4243

4344
// Section 2.

simplytest/test_run.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ func callSortTest(origin, verify []int) {
5353
q = append(q, CallCycleSort(origin, verify, "cycle sort"))
5454
q = append(q, CallOddEvenSort(origin, verify, "odd-even sort"))
5555
q = append(q, CallOddEvenMergeSort(origin, verify, "odd-even merge sort"))
56+
q = append(q, CallParallelOddEvenMergeSort(origin, verify, "parallel odd-even merge sort"))
5657
var pf string = ""
5758

5859
pf += fmt.Sprintf("\n+%s+\n", strings.Repeat("-", 97))

sorts/bitonic_sort.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -43,18 +43,3 @@ func greatestPowerOfTwoLessThan(n int) int {
4343
}
4444
return k >> 1
4545
}
46-
func BottomUpBitonicSort(a []int) {
47-
48-
}
49-
50-
func bottomUpBitonicSort(a []int, len int) {
51-
52-
for blockSize := 2; blockSize <= len; blockSize <<= 1 {
53-
for subPart := blockSize / 2; subPart > 0; subPart >>= 1 {
54-
55-
for i := 0; i < len; i++ {
56-
57-
}
58-
}
59-
}
60-
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
author : kdgyun
3+
4+
link : https://st-lab.tistory.com
5+
link : https://github.com/kdgyun
6+
*/
7+
8+
package sorts
9+
10+
import (
11+
"runtime"
12+
"sync"
13+
)
14+
15+
func ParallelOddEvenMergeSort(a []int) {
16+
runtime.GOMAXPROCS(runtime.NumCPU())
17+
parallelOddEvenMergeSort(a, 0, len(a))
18+
}
19+
20+
func parallelOddEvenMergeSort(a []int, lo, hi int) {
21+
if hi-lo > 1 {
22+
mid := (hi + lo) >> 1
23+
// 2048 is threshold
24+
if hi-lo > 2048 {
25+
26+
var wg sync.WaitGroup
27+
wg.Add(1)
28+
29+
go func() {
30+
defer wg.Done()
31+
parallelOddEvenMergeSort(a, lo, mid)
32+
}()
33+
parallelOddEvenMergeSort(a, mid, hi)
34+
wg.Wait()
35+
parallelOddEvenMerge(a, lo, hi, 1)
36+
} else {
37+
basicOddEvenMergeSort(a, lo, mid)
38+
basicOddEvenMergeSort(a, mid, hi)
39+
basicOddEvenMerge(a, lo, hi, 1)
40+
}
41+
}
42+
}
43+
44+
func parallelOddEvenMerge(a []int, lo, hi, dist int) {
45+
subDist := dist << 1
46+
if subDist < (hi - lo) {
47+
48+
if subDist < 32 {
49+
var wg sync.WaitGroup
50+
wg.Add(1)
51+
52+
go func() {
53+
defer wg.Done()
54+
parallelOddEvenMerge(a, lo, hi, subDist)
55+
}()
56+
parallelOddEvenMerge(a, lo+dist, hi, subDist)
57+
wg.Wait()
58+
} else {
59+
basicOddEvenMerge(a, lo, hi, subDist)
60+
basicOddEvenMerge(a, lo+dist, hi, subDist)
61+
}
62+
for i := lo + dist; i+dist < hi; i += subDist {
63+
64+
if a[i] > a[i+dist] {
65+
a[i], a[i+dist] = a[i+dist], a[i]
66+
}
67+
}
68+
} else {
69+
if a[lo] > a[lo+dist] {
70+
a[lo], a[lo+dist] = a[lo+dist], a[lo]
71+
}
72+
}
73+
}
74+
75+
func basicOddEvenMergeSort(a []int, lo, hi int) {
76+
if hi-lo > 1 {
77+
mid := (hi + lo) >> 1
78+
basicOddEvenMergeSort(a, lo, mid)
79+
basicOddEvenMergeSort(a, mid, hi)
80+
basicOddEvenMerge(a, lo, hi, 1)
81+
}
82+
}
83+
84+
func basicOddEvenMerge(a []int, lo, hi, dist int) {
85+
subDist := dist << 1
86+
if subDist < (hi - lo) {
87+
basicOddEvenMerge(a, lo, hi, subDist)
88+
basicOddEvenMerge(a, lo+dist, hi, subDist)
89+
for i := lo + dist; i+dist < hi; i += subDist {
90+
91+
if a[i] > a[i+dist] {
92+
a[i], a[i+dist] = a[i+dist], a[i]
93+
}
94+
}
95+
} else {
96+
if a[lo] > a[lo+dist] {
97+
a[lo], a[lo+dist] = a[lo+dist], a[lo]
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)