Start goroutines once and use channels to distribute work

This commit is contained in:
Peter J. Holzer 2021-07-13 12:09:17 +02:00 committed by Peter J. Holzer
parent cfb18dec75
commit 5d3af658d7
1 changed files with 25 additions and 10 deletions

View File

@ -5,17 +5,24 @@ import (
"os" "os"
"runtime" "runtime"
"strconv" "strconv"
"sync"
"time" "time"
) )
var markGroup sync.WaitGroup type work struct {
i int64
n0, n1 int64
}
func markMultiples(sieve []uint64, i int64, n0, n1 int64) { type result bool
for j := n0; j < n1; j += 2 * i {
func markMultiples(sieve []uint64, workCh chan work, resultCh chan result) {
for {
w := <-workCh
for j := w.n0; j < w.n1; j += 2 * w.i {
sieve[j>>7] |= 1 << ((j & 0x7F) >> 1) sieve[j>>7] |= 1 << ((j & 0x7F) >> 1)
} }
markGroup.Done() resultCh <- true
}
} }
func main() { func main() {
@ -26,8 +33,13 @@ func main() {
nCpus := int64(runtime.NumCPU()) nCpus := int64(runtime.NumCPU())
t0 := time.Now() t0 := time.Now()
sieve := make([]uint64, (n>>7)+1) sieve := make([]uint64, (n>>7)+1)
var found int64 workCh := make(chan work)
resultCh := make(chan result)
var i int64 var i int64
for i = 0; i < nCpus; i++ {
go markMultiples(sieve, workCh, resultCh)
}
var found int64
i = 2 i = 2
found++ found++
for i = 3; i < n; i += 2 { for i = 3; i < n; i += 2 {
@ -41,16 +53,19 @@ func main() {
if n / i < i { if n / i < i {
continue; continue;
} }
workers := 0
for j := i * i; j < n; j = jnext { for j := i * i; j < n; j = jnext {
jnext = ((n-j)/(2*i)/p+1)*(2*i) + j jnext = ((n-j)/(2*i)/p+1)*(2*i) + j
if jnext > n { if jnext > n {
jnext = n jnext = n
} }
markGroup.Add(1) workCh <-work{ i, j, jnext }
go markMultiples(sieve, i, j, jnext) workers++
p-- p--
} }
markGroup.Wait() for k := 0; k < workers; k++ {
_ = <-resultCh
}
} }
} }
d := time.Since(t0) d := time.Since(t0)