Skip to content

Commit

Permalink
add : Parallel Odd-Even Merge Sort
Browse files Browse the repository at this point in the history
  • Loading branch information
kdgyun committed Feb 24, 2022
1 parent 46cba63 commit f68db69
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 17 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ Algorithms covered so far:
| [Cycle Sort](#cycle-sort) | CycleSort |
| [Odd-Even Sort](#odd-even-sort) | OddEvenSort |
| [Odd-Even Merge Sort](#odd-even-merge-sort) | OddEvenMergeSort |
| [Odd-Even Merge Sort (parallel)](#odd-even-merge-sort) | ParallelOddEvenMergeSort |


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

\[todo] add parallel-ver.



<br />
Expand Down
13 changes: 13 additions & 0 deletions glob_bench_test/sort_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,3 +364,16 @@ func BenchmarkOddEvenMergeSort(b *testing.B) {
b.StopTimer()
}
}

func BenchmarkParallelOddEvenMergeSort(b *testing.B) {
b.StopTimer()
unsorted := sliceBuilder(lengthforbench)
test := make([]int, len(unsorted))

for i := 0; i < b.N; i++ {
copy(test, unsorted)
b.StartTimer()
sorts.ParallelOddEvenMergeSort(test)
b.StopTimer()
}
}
8 changes: 8 additions & 0 deletions glob_bench_test/sort_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ func TestSort(t *testing.T) {
if !reflect.DeepEqual(test, verify) {
t.Error("Wrong result [odd-even sort]")
}

test = make([]int, len(origin))
copy(test, origin)
t.Run("parallel odd-even merge sort", func(t *testing.T) { sorts.ParallelOddEvenMergeSort(test) })

if !reflect.DeepEqual(test, verify) {
t.Error("Wrong result [parallel odd-even sort]")
}
size <<= 2
}
}
22 changes: 21 additions & 1 deletion simplytest/base_sort_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ func CallOddEvenSort(origin []int, verify []int, callName string) OutputForm {
func CallOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
size := len(origin)
if (size & (size - 1)) != 0 {
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("top-down odd-even sort can't run"))
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("odd-even sort can't run"))
fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
return OutputForm{false, callName, -1, false, ""}
}
Expand All @@ -384,3 +384,23 @@ func CallOddEvenMergeSort(origin []int, verify []int, callName string) OutputFor
}
return OutputForm{false, callName, -1, false, ""}
}

func CallParallelOddEvenMergeSort(origin []int, verify []int, callName string) OutputForm {
size := len(origin)
if (size & (size - 1)) != 0 {
fmt.Println(aurora.Bold(aurora.BrightRed("[Skip] ")), aurora.BrightRed("parallel odd-even sort can't run"))
fmt.Println(aurora.BrightYellow("\tIf you want to use this sort algorithm,\n\tlength of the array must be a power of 2."))
return OutputForm{false, callName, -1, false, ""}
}
if PARALLEL_ODDEVEN_MERGE_SORT {
test := make([]int, len(origin))
copy(test, origin)
fmt.Printf("runing %s...\n", callName)
start := time.Now()
sorts.ParallelOddEvenMergeSort(test)
end := time.Since(start)
eq, err := Equal(verify, test)
return OutputForm{true, callName, end.Nanoseconds(), eq, err}
}
return OutputForm{false, callName, -1, false, ""}
}
1 change: 1 addition & 0 deletions simplytest/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (
CYCLE_SORT Activate = true
ODDEVEN_SORT Activate = true
ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
PARALLEL_ODDEVEN_MERGE_SORT Activate = true // The length n of the array must be a power of 2
)

// Section 2.
Expand Down
1 change: 1 addition & 0 deletions simplytest/test_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func callSortTest(origin, verify []int) {
q = append(q, CallCycleSort(origin, verify, "cycle sort"))
q = append(q, CallOddEvenSort(origin, verify, "odd-even sort"))
q = append(q, CallOddEvenMergeSort(origin, verify, "odd-even merge sort"))
q = append(q, CallParallelOddEvenMergeSort(origin, verify, "parallel odd-even merge sort"))
var pf string = ""

pf += fmt.Sprintf("\n+%s+\n", strings.Repeat("-", 97))
Expand Down
15 changes: 0 additions & 15 deletions sorts/bitonic_sort.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,3 @@ func greatestPowerOfTwoLessThan(n int) int {
}
return k >> 1
}
func BottomUpBitonicSort(a []int) {

}

func bottomUpBitonicSort(a []int, len int) {

for blockSize := 2; blockSize <= len; blockSize <<= 1 {
for subPart := blockSize / 2; subPart > 0; subPart >>= 1 {

for i := 0; i < len; i++ {

}
}
}
}
100 changes: 100 additions & 0 deletions sorts/parallel_odd_even_merge_sort.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
author : kdgyun
link : https://st-lab.tistory.com
link : https://github.com/kdgyun
*/

package sorts

import (
"runtime"
"sync"
)

func ParallelOddEvenMergeSort(a []int) {
runtime.GOMAXPROCS(runtime.NumCPU())
parallelOddEvenMergeSort(a, 0, len(a))
}

func parallelOddEvenMergeSort(a []int, lo, hi int) {
if hi-lo > 1 {
mid := (hi + lo) >> 1
// 2048 is threshold
if hi-lo > 2048 {

var wg sync.WaitGroup
wg.Add(1)

go func() {
defer wg.Done()
parallelOddEvenMergeSort(a, lo, mid)
}()
parallelOddEvenMergeSort(a, mid, hi)
wg.Wait()
parallelOddEvenMerge(a, lo, hi, 1)
} else {
basicOddEvenMergeSort(a, lo, mid)
basicOddEvenMergeSort(a, mid, hi)
basicOddEvenMerge(a, lo, hi, 1)
}
}
}

func parallelOddEvenMerge(a []int, lo, hi, dist int) {
subDist := dist << 1
if subDist < (hi - lo) {

if subDist < 32 {
var wg sync.WaitGroup
wg.Add(1)

go func() {
defer wg.Done()
parallelOddEvenMerge(a, lo, hi, subDist)
}()
parallelOddEvenMerge(a, lo+dist, hi, subDist)
wg.Wait()
} else {
basicOddEvenMerge(a, lo, hi, subDist)
basicOddEvenMerge(a, lo+dist, hi, subDist)
}
for i := lo + dist; i+dist < hi; i += subDist {

if a[i] > a[i+dist] {
a[i], a[i+dist] = a[i+dist], a[i]
}
}
} else {
if a[lo] > a[lo+dist] {
a[lo], a[lo+dist] = a[lo+dist], a[lo]
}
}
}

func basicOddEvenMergeSort(a []int, lo, hi int) {
if hi-lo > 1 {
mid := (hi + lo) >> 1
basicOddEvenMergeSort(a, lo, mid)
basicOddEvenMergeSort(a, mid, hi)
basicOddEvenMerge(a, lo, hi, 1)
}
}

func basicOddEvenMerge(a []int, lo, hi, dist int) {
subDist := dist << 1
if subDist < (hi - lo) {
basicOddEvenMerge(a, lo, hi, subDist)
basicOddEvenMerge(a, lo+dist, hi, subDist)
for i := lo + dist; i+dist < hi; i += subDist {

if a[i] > a[i+dist] {
a[i], a[i+dist] = a[i+dist], a[i]
}
}
} else {
if a[lo] > a[lo+dist] {
a[lo], a[lo+dist] = a[lo+dist], a[lo]
}
}
}

0 comments on commit f68db69

Please sign in to comment.