From e722f0ae684a20681c9caad2a1689b72b322206e Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Tue, 29 Mar 2022 11:32:12 -0700 Subject: [PATCH] init --- gogogog/main.go | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 gogogog/main.go diff --git a/gogogog/main.go b/gogogog/main.go new file mode 100644 index 0000000..870bf8d --- /dev/null +++ b/gogogog/main.go @@ -0,0 +1,112 @@ +package main + +import ( + "fmt" + "math/rand" + "time" +) + +// var MAXGOROUTINES = 10000 + +func Cqsort(s []int, MAXGOROUTINES int) { + if len(s) <= 1 { + return + } + workers := make(chan int, MAXGOROUTINES-1) + for i := 0; i < (MAXGOROUTINES - 1); i++ { + workers <- 1 + } + cqsort(s, nil, workers) +} + +func cqsort(s []int, done chan int, workers chan int) { + // report to caller that we're finished + if done != nil { + defer func() { done <- 1 }() + } + + if len(s) <= 1 { + return + } + // since we may use the doneChannel synchronously + // we need to buffer it so the synchronous code will + // continue executing and not block waiting for a read + doneChannel := make(chan int, 1) + + pivotIdx := partition(s) + + select { + case <-workers: + // if we have spare workers, use a goroutine + // for parallelization + go cqsort(s[:pivotIdx+1], doneChannel, workers) + default: + // if no spare workers, sort synchronously + cqsort(s[:pivotIdx+1], nil, workers) + // calling this here as opposed to using the defer + doneChannel <- 1 + } + // use the existing goroutine to sort above the pivot + cqsort(s[pivotIdx+1:], nil, workers) + // if we used a goroutine we'll need to wait for + // the async signal on this channel, if not there + // will already be a value in the channel and it shouldn't block + <-doneChannel + return +} + +func partition(s []int) (swapIdx int) { + pivotIdx, pivot := pickPivot(s) + // swap right-most element and pivot + s[len(s)-1], s[pivotIdx] = s[pivotIdx], s[len(s)-1] + // sort elements keeping track of pivot's idx + for i := 0; i < len(s)-1; i++ { + if s[i] < pivot { + s[i], s[swapIdx] = s[swapIdx], s[i] + swapIdx++ + } + } + // swap pivot back to its place and return + s[swapIdx], s[len(s)-1] = s[len(s)-1], s[swapIdx] + return +} + +func pickPivot(s []int) (pivotIdx int, pivot int) { + pivotIdx = rand.Intn(len(s)) + pivot = s[pivotIdx] + return +} + +func Qsort(s []int) { + if len(s) <= 1 { + return + } + pivotIdx := partition(s) + Qsort(s[:pivotIdx+1]) + Qsort(s[pivotIdx+1:]) + return +} + +func main() { + + sortSize := 1000000 + // MAXGOROUTINES := 1 + unsorted := make([]int, 0, sortSize) + + // MAXGOROUTINES = 100000 + start := time.Now() + unsorted = rand.Perm(sortSize) + Cqsort(unsorted, 8) + duration := time.Since(start) + + fmt.Println("goroutines", duration) + + // MAXGOROUTINES = 1 + start = time.Now() + unsorted = rand.Perm(sortSize) + Cqsort(unsorted, 1) + duration = time.Since(start) + + fmt.Println(duration) + +}