Last active
June 11, 2019 06:10
-
-
Save pgbytes/ec23c906b83eab44b489011bc0b445d3 to your computer and use it in GitHub Desktop.
concurrent merge sort
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
goos: darwin | |
goarch: amd64 | |
pkg: puzzles-golang/algos/mergesort | |
BenchmarkConcurrentMergeSort_20-12 100000 15146 ns/op | |
BenchmarkConcurrentMergeSort_50-12 50000 32069 ns/op | |
BenchmarkConcurrentMergeSort_80-12 30000 49633 ns/op | |
BenchmarkConcurrentMergeSort_200-12 10000 104311 ns/op | |
BenchmarkConcurrentMergeSort_500-12 10000 221560 ns/op | |
BenchmarkConcurrentMergeSort_5000-12 500 2779299 ns/op | |
BenchmarkConcurrentMergeSort_100000-12 20 57669829 ns/op | |
BenchmarkStdMergeSort_20-12 2000000 862 ns/op | |
BenchmarkStdMergeSort_50-12 500000 2565 ns/op | |
BenchmarkStdMergeSort_80-12 300000 4462 ns/op | |
BenchmarkStdMergeSort_200-12 100000 13663 ns/op | |
BenchmarkStdMergeSort_500-12 30000 45032 ns/op | |
BenchmarkStdMergeSort_5000-12 2000 738091 ns/op | |
BenchmarkStdMergeSort_100000-12 100 18417434 ns/op |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mergesort | |
// This is the modified merge sort using go concurrency | |
// if A of length 2x is split into X & Y of size x each, | |
// sorting of these can take place concurrently. | |
func SortConcurrent(arr []int) []int { | |
ch := make(chan int, len(arr)) | |
sortConcurrentIntoChannel(arr, ch) | |
var sorted []int | |
for v := range ch { | |
sorted = append(sorted, v) | |
} | |
return sorted | |
} | |
func sortConcurrentIntoChannel(arr []int, ch chan int) { | |
// recursion exit | |
defer close(ch) | |
if len(arr) <= 1 { | |
if len(arr) == 1 { | |
ch <- arr[0] | |
} | |
return | |
} | |
mid := len(arr)/2 | |
s1 := make(chan int, mid) | |
s2 := make(chan int, len(arr) - mid) | |
go sortConcurrentIntoChannel(arr[:mid], s1) | |
go sortConcurrentIntoChannel(arr[mid:], s2) | |
mergeConcurrent(s1, s2, ch) | |
} | |
func mergeConcurrent(s1, s2, ch chan int) { | |
// v, ok = <- s; receiving value from channel, ok returns false when there is no more elements in channel s | |
v1, ok1 := <- s1 | |
v2, ok2 := <- s2 | |
for ok1 && ok2 { | |
if v1 < v2 { | |
updateConcurrent(s1, ch, &v1, &ok1) | |
} else { | |
updateConcurrent(s2, ch, &v2, &ok2) | |
} | |
} | |
for ok1 { | |
updateConcurrent(s1, ch, &v1, &ok1) | |
} | |
for ok2 { | |
updateConcurrent(s2, ch, &v2, &ok2) | |
} | |
} | |
func updateConcurrent(s chan int, ch chan int, v *int, ok *bool) { | |
ch <- *v | |
*v, *ok = <- s | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mergesort | |
import ( | |
"testing" | |
) | |
func BenchmarkConcurrentMergeSort_20(b *testing.B) { | |
sample := generateRandomArrayInt(20, 100) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func BenchmarkConcurrentMergeSort_50(b *testing.B) { | |
sample := generateRandomArrayInt(50, 100) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func BenchmarkConcurrentMergeSort_80(b *testing.B) { | |
sample := generateRandomArrayInt(80, 300) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func BenchmarkConcurrentMergeSort_200(b *testing.B) { | |
sample := generateRandomArrayInt(200, 500) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func BenchmarkConcurrentMergeSort_500(b *testing.B) { | |
sample := generateRandomArrayInt(500, 1000) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func BenchmarkConcurrentMergeSort_5000(b *testing.B) { | |
sample := generateRandomArrayInt(5000, 10000) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func BenchmarkConcurrentMergeSort_100000(b *testing.B) { | |
sample := generateRandomArrayInt(100000, 400000) | |
benchmarkConcurrentSort(sample, b) | |
} | |
func benchmarkConcurrentSort(sample []int, b *testing.B) { | |
for n := 0; n < b.N; n++ { | |
SortConcurrent(sample) | |
} | |
} | |
func generateRandomArrayInt(size int, limit int) []int { | |
var sample []int | |
seed := rand.NewSource(time.Now().UnixNano()) | |
rnd := rand.New(seed) | |
for i := 0; i < size; i++ { | |
sample = append(sample, rnd.Intn(limit)) | |
} | |
return sample | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mergesort | |
// This is the normal merge sort with sequential flow of steps. | |
func Sort(arr []int) []int { | |
// recursion exit | |
if len(arr) <= 1 { | |
return arr | |
} | |
// split the arrays into half | |
mid := len(arr) / 2 | |
// recursively split the halves into further halves, till there is only 1 element in the array. | |
// putting them on the stack while splitting | |
s1 := Sort(arr[:mid]) | |
s2 := Sort(arr[mid:]) | |
// recursively merge all the split arrays | |
return merge(s1, s2) | |
} | |
func merge(arr1 []int, arr2 []int) []int { | |
size1 := len(arr1) | |
size2 := len(arr2) | |
finalArr := make([]int, size1+size2) | |
i := 0 | |
j := 0 | |
index := 0 | |
for i < size1 && j < size2 { | |
if arr1[i] < arr2[j] { | |
update(finalArr, arr1, &index, &i) | |
} else { | |
update(finalArr, arr2, &index, &j) | |
} | |
} | |
for i < size1 { | |
update(finalArr, arr1, &index, &i) | |
} | |
for j < size2 { | |
update(finalArr, arr2, &index, &j) | |
} | |
return finalArr | |
} | |
func update(finalArr []int, arr []int, index *int, incrementIndex *int) { | |
finalArr[*index] = arr[*incrementIndex] | |
*incrementIndex++ | |
*index++ | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package mergesort | |
import ( | |
"math/rand" | |
"testing" | |
"time" | |
) | |
func BenchmarkStdMergeSort_20(b *testing.B) { | |
sample := generateRandomArrayInt(20, 100) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func BenchmarkStdMergeSort_50(b *testing.B) { | |
sample := generateRandomArrayInt(50, 100) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func BenchmarkStdMergeSort_80(b *testing.B) { | |
sample := generateRandomArrayInt(80, 300) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func BenchmarkStdMergeSort_200(b *testing.B) { | |
sample := generateRandomArrayInt(200, 500) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func BenchmarkStdMergeSort_500(b *testing.B) { | |
sample := generateRandomArrayInt(500, 1000) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func BenchmarkStdMergeSort_5000(b *testing.B) { | |
sample := generateRandomArrayInt(5000, 10000) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func BenchmarkStdMergeSort_100000(b *testing.B) { | |
sample := generateRandomArrayInt(100000, 400000) | |
//b.Logf("benchmarking standard merge sort with size: %d", len(sample)) | |
benchmarkSort(sample, b) | |
} | |
func generateRandomArrayInt(size int, limit int) []int { | |
var sample []int | |
seed := rand.NewSource(time.Now().UnixNano()) | |
rnd := rand.New(seed) | |
for i := 0; i < size; i++ { | |
sample = append(sample, rnd.Intn(limit)) | |
} | |
return sample | |
} | |
func benchmarkSort(sample []int, b *testing.B) { | |
for n := 0; n < b.N; n++ { | |
Sort(sample) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment