>>103561263
func Compute(n int, m *sync.Map) *big.Int {
if val, exists := m.Load(n); exists {
return val.(*big.Int)
}
res := new(big.Int).Add(Compute(n-1, m), Compute(n-2, m))
m.Store(n, res)
return res
}
type result struct {
num int
val *big.Int
}
type processchans struct {
input chan result
output chan *big.Int
done chan struct{}
}
func processResults(chans processchans) {
var nextExpect int
backlog := make(map[int]*big.Int)
for item := range chans.input {
if item.num == nextExpect {
chans.output <- item.val
nextExpect++
for {
if val, exists := backlog[nextExpect]; exists {
chans.output <- val
nextExpect++
} else {
break
}
}
} else {
backlog[item.num] = item.val
}
}
close(chans.output)
chans.done <- struct{}{}
}
var numToFib = 5000
func main() {
numcpu := runtime.NumCPU()
runtime.GOMAXPROCS(numcpu)
memo := sync.Map{}
memo.Store(0, big.NewInt(0))
memo.Store(1, big.NewInt(1))
var wg sync.WaitGroup
chans := processchans{
input: make(chan result, numcpu),
output: make(chan *big.Int, numcpu),
done: make(chan struct{}),
}
go processResults(chans)
jobs := make(chan int, numToFib)
for range numcpu {
wg.Add(1)
go func() {
defer wg.Done()
for n := range jobs {
chans.input <- result{num: n, val: Compute(n, &memo)}
}
}()
}
go func() {
for i := range numToFib {
jobs <- i
}
close(jobs)
}()
go func() {
wg.Wait()
close(chans.input)
}()
for res := range chans.output {
fmt.Println(res)
}
<-chans.done
}