Nth Fibonacci number in Go using recursion and concurrency
up vote
1
down vote
favorite
The Java Code I'm attempting to translate. I've been trying to implement this java method of getting the nth Fibonacci number in Go but I can't seem to get my code past the number Fibonacci number 35 before it crashes. This method is supposed to be very inefficient but not so inefficient that it doesn't complete.
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
func newFibonacci(n float64) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64)
c2 := make(chan float64)
if f.num <= 1 {
f.answer = n
} else {
go func() {
fib1 := newFibonacci(n - 1)
c2 <- fib1.answer
}()
go func() {
fib2 := newFibonacci(n - 2)
c1 <- fib2.answer
}()
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers{
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
f := newFibonacci(value)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
go recursion concurrency fibonacci goroutine
New contributor
add a comment |
up vote
1
down vote
favorite
The Java Code I'm attempting to translate. I've been trying to implement this java method of getting the nth Fibonacci number in Go but I can't seem to get my code past the number Fibonacci number 35 before it crashes. This method is supposed to be very inefficient but not so inefficient that it doesn't complete.
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
func newFibonacci(n float64) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64)
c2 := make(chan float64)
if f.num <= 1 {
f.answer = n
} else {
go func() {
fib1 := newFibonacci(n - 1)
c2 <- fib1.answer
}()
go func() {
fib2 := newFibonacci(n - 2)
c1 <- fib2.answer
}()
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers{
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
f := newFibonacci(value)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
go recursion concurrency fibonacci goroutine
New contributor
You have a combinatorial explodion: cs.toronto.edu/~gfb/csc104/2016W/Lectures/…
– peterSO
Nov 5 at 2:24
"supposed to be very efficient" and then "recursive fibonacci implementation", these two doesn't go together, period. An efficient fibonacci implementation uses a loop, and isn't recursive. The recursive variant is only good for one thing and that is teaching about the pitfalls of recursion.
– Lasse Vågsæther Karlsen
Nov 5 at 12:20
"supposed to be very inefficient" and I am using this to teach the pitfalls. I'm hoping to implement a worker pool and limit the amount of workers to the number of available CPUs. I would just like to get this working to show the differences.
– Swade
Nov 5 at 17:15
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
The Java Code I'm attempting to translate. I've been trying to implement this java method of getting the nth Fibonacci number in Go but I can't seem to get my code past the number Fibonacci number 35 before it crashes. This method is supposed to be very inefficient but not so inefficient that it doesn't complete.
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
func newFibonacci(n float64) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64)
c2 := make(chan float64)
if f.num <= 1 {
f.answer = n
} else {
go func() {
fib1 := newFibonacci(n - 1)
c2 <- fib1.answer
}()
go func() {
fib2 := newFibonacci(n - 2)
c1 <- fib2.answer
}()
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers{
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
f := newFibonacci(value)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
go recursion concurrency fibonacci goroutine
New contributor
The Java Code I'm attempting to translate. I've been trying to implement this java method of getting the nth Fibonacci number in Go but I can't seem to get my code past the number Fibonacci number 35 before it crashes. This method is supposed to be very inefficient but not so inefficient that it doesn't complete.
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
func newFibonacci(n float64) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64)
c2 := make(chan float64)
if f.num <= 1 {
f.answer = n
} else {
go func() {
fib1 := newFibonacci(n - 1)
c2 <- fib1.answer
}()
go func() {
fib2 := newFibonacci(n - 2)
c1 <- fib2.answer
}()
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers{
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
f := newFibonacci(value)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
go recursion concurrency fibonacci goroutine
go recursion concurrency fibonacci goroutine
New contributor
New contributor
New contributor
asked Nov 5 at 1:36
Swade
62
62
New contributor
New contributor
You have a combinatorial explodion: cs.toronto.edu/~gfb/csc104/2016W/Lectures/…
– peterSO
Nov 5 at 2:24
"supposed to be very efficient" and then "recursive fibonacci implementation", these two doesn't go together, period. An efficient fibonacci implementation uses a loop, and isn't recursive. The recursive variant is only good for one thing and that is teaching about the pitfalls of recursion.
– Lasse Vågsæther Karlsen
Nov 5 at 12:20
"supposed to be very inefficient" and I am using this to teach the pitfalls. I'm hoping to implement a worker pool and limit the amount of workers to the number of available CPUs. I would just like to get this working to show the differences.
– Swade
Nov 5 at 17:15
add a comment |
You have a combinatorial explodion: cs.toronto.edu/~gfb/csc104/2016W/Lectures/…
– peterSO
Nov 5 at 2:24
"supposed to be very efficient" and then "recursive fibonacci implementation", these two doesn't go together, period. An efficient fibonacci implementation uses a loop, and isn't recursive. The recursive variant is only good for one thing and that is teaching about the pitfalls of recursion.
– Lasse Vågsæther Karlsen
Nov 5 at 12:20
"supposed to be very inefficient" and I am using this to teach the pitfalls. I'm hoping to implement a worker pool and limit the amount of workers to the number of available CPUs. I would just like to get this working to show the differences.
– Swade
Nov 5 at 17:15
You have a combinatorial explodion: cs.toronto.edu/~gfb/csc104/2016W/Lectures/…
– peterSO
Nov 5 at 2:24
You have a combinatorial explodion: cs.toronto.edu/~gfb/csc104/2016W/Lectures/…
– peterSO
Nov 5 at 2:24
"supposed to be very efficient" and then "recursive fibonacci implementation", these two doesn't go together, period. An efficient fibonacci implementation uses a loop, and isn't recursive. The recursive variant is only good for one thing and that is teaching about the pitfalls of recursion.
– Lasse Vågsæther Karlsen
Nov 5 at 12:20
"supposed to be very efficient" and then "recursive fibonacci implementation", these two doesn't go together, period. An efficient fibonacci implementation uses a loop, and isn't recursive. The recursive variant is only good for one thing and that is teaching about the pitfalls of recursion.
– Lasse Vågsæther Karlsen
Nov 5 at 12:20
"supposed to be very inefficient" and I am using this to teach the pitfalls. I'm hoping to implement a worker pool and limit the amount of workers to the number of available CPUs. I would just like to get this working to show the differences.
– Swade
Nov 5 at 17:15
"supposed to be very inefficient" and I am using this to teach the pitfalls. I'm hoping to implement a worker pool and limit the amount of workers to the number of available CPUs. I would just like to get this working to show the differences.
– Swade
Nov 5 at 17:15
add a comment |
2 Answers
2
active
oldest
votes
up vote
0
down vote
I suggest you do the math behind how many goroutines you're actually launching.
Your first call spawns two goroutines. Each of those spawn two further goroutines. The total number of goroutines spawned will be 2^1 + 2^2 + 2^3 + ... + 2^n
. While a lot of these will exit before you reach the number below, it's still a lot of goroutines.
add a comment |
up vote
0
down vote
You program create exponential number of go routines. That comes with context switching latency. Try to run it for limited number of go routines. See following code where i run it for limited number of go routines:
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
type goRoutineManager struct {
goRoutineCnt chan bool
}
func (g *goRoutineManager) Run(f func()) {
select {
case g.goRoutineCnt <- true:
go func() {
f()
<-g.goRoutineCnt
}()
default:
f()
}
}
func NewGoRoutineManager(goRoutineLimit int) *goRoutineManager {
return &goRoutineManager{
goRoutineCnt: make(chan bool, goRoutineLimit),
}
}
func newFibonacci(n float64, gm *goRoutineManager) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64, 1)
c2 := make(chan float64, 1)
if f.num <= 1 {
f.answer = n
} else {
gm.Run(func() {
fib1 := newFibonacci(n-1, gm)
c2 <- fib1.answer
})
gm.Run(func() {
fib2 := newFibonacci(n-2, gm)
c1 <- fib2.answer
})
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40} //{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers {
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
gm := NewGoRoutineManager(3)
f := newFibonacci(value, gm)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
I suggest you do the math behind how many goroutines you're actually launching.
Your first call spawns two goroutines. Each of those spawn two further goroutines. The total number of goroutines spawned will be 2^1 + 2^2 + 2^3 + ... + 2^n
. While a lot of these will exit before you reach the number below, it's still a lot of goroutines.
add a comment |
up vote
0
down vote
I suggest you do the math behind how many goroutines you're actually launching.
Your first call spawns two goroutines. Each of those spawn two further goroutines. The total number of goroutines spawned will be 2^1 + 2^2 + 2^3 + ... + 2^n
. While a lot of these will exit before you reach the number below, it's still a lot of goroutines.
add a comment |
up vote
0
down vote
up vote
0
down vote
I suggest you do the math behind how many goroutines you're actually launching.
Your first call spawns two goroutines. Each of those spawn two further goroutines. The total number of goroutines spawned will be 2^1 + 2^2 + 2^3 + ... + 2^n
. While a lot of these will exit before you reach the number below, it's still a lot of goroutines.
I suggest you do the math behind how many goroutines you're actually launching.
Your first call spawns two goroutines. Each of those spawn two further goroutines. The total number of goroutines spawned will be 2^1 + 2^2 + 2^3 + ... + 2^n
. While a lot of these will exit before you reach the number below, it's still a lot of goroutines.
answered Nov 5 at 3:55
Luke Joshua Park
4,73051630
4,73051630
add a comment |
add a comment |
up vote
0
down vote
You program create exponential number of go routines. That comes with context switching latency. Try to run it for limited number of go routines. See following code where i run it for limited number of go routines:
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
type goRoutineManager struct {
goRoutineCnt chan bool
}
func (g *goRoutineManager) Run(f func()) {
select {
case g.goRoutineCnt <- true:
go func() {
f()
<-g.goRoutineCnt
}()
default:
f()
}
}
func NewGoRoutineManager(goRoutineLimit int) *goRoutineManager {
return &goRoutineManager{
goRoutineCnt: make(chan bool, goRoutineLimit),
}
}
func newFibonacci(n float64, gm *goRoutineManager) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64, 1)
c2 := make(chan float64, 1)
if f.num <= 1 {
f.answer = n
} else {
gm.Run(func() {
fib1 := newFibonacci(n-1, gm)
c2 <- fib1.answer
})
gm.Run(func() {
fib2 := newFibonacci(n-2, gm)
c1 <- fib2.answer
})
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40} //{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers {
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
gm := NewGoRoutineManager(3)
f := newFibonacci(value, gm)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
add a comment |
up vote
0
down vote
You program create exponential number of go routines. That comes with context switching latency. Try to run it for limited number of go routines. See following code where i run it for limited number of go routines:
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
type goRoutineManager struct {
goRoutineCnt chan bool
}
func (g *goRoutineManager) Run(f func()) {
select {
case g.goRoutineCnt <- true:
go func() {
f()
<-g.goRoutineCnt
}()
default:
f()
}
}
func NewGoRoutineManager(goRoutineLimit int) *goRoutineManager {
return &goRoutineManager{
goRoutineCnt: make(chan bool, goRoutineLimit),
}
}
func newFibonacci(n float64, gm *goRoutineManager) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64, 1)
c2 := make(chan float64, 1)
if f.num <= 1 {
f.answer = n
} else {
gm.Run(func() {
fib1 := newFibonacci(n-1, gm)
c2 <- fib1.answer
})
gm.Run(func() {
fib2 := newFibonacci(n-2, gm)
c1 <- fib2.answer
})
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40} //{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers {
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
gm := NewGoRoutineManager(3)
f := newFibonacci(value, gm)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
add a comment |
up vote
0
down vote
up vote
0
down vote
You program create exponential number of go routines. That comes with context switching latency. Try to run it for limited number of go routines. See following code where i run it for limited number of go routines:
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
type goRoutineManager struct {
goRoutineCnt chan bool
}
func (g *goRoutineManager) Run(f func()) {
select {
case g.goRoutineCnt <- true:
go func() {
f()
<-g.goRoutineCnt
}()
default:
f()
}
}
func NewGoRoutineManager(goRoutineLimit int) *goRoutineManager {
return &goRoutineManager{
goRoutineCnt: make(chan bool, goRoutineLimit),
}
}
func newFibonacci(n float64, gm *goRoutineManager) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64, 1)
c2 := make(chan float64, 1)
if f.num <= 1 {
f.answer = n
} else {
gm.Run(func() {
fib1 := newFibonacci(n-1, gm)
c2 <- fib1.answer
})
gm.Run(func() {
fib2 := newFibonacci(n-2, gm)
c1 <- fib2.answer
})
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40} //{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers {
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
gm := NewGoRoutineManager(3)
f := newFibonacci(value, gm)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
You program create exponential number of go routines. That comes with context switching latency. Try to run it for limited number of go routines. See following code where i run it for limited number of go routines:
package main
import (
"fmt"
"time"
)
type Fibonacci struct {
num float64
answer float64
}
type goRoutineManager struct {
goRoutineCnt chan bool
}
func (g *goRoutineManager) Run(f func()) {
select {
case g.goRoutineCnt <- true:
go func() {
f()
<-g.goRoutineCnt
}()
default:
f()
}
}
func NewGoRoutineManager(goRoutineLimit int) *goRoutineManager {
return &goRoutineManager{
goRoutineCnt: make(chan bool, goRoutineLimit),
}
}
func newFibonacci(n float64, gm *goRoutineManager) *Fibonacci {
f := new(Fibonacci)
f.num = n
c1 := make(chan float64, 1)
c2 := make(chan float64, 1)
if f.num <= 1 {
f.answer = n
} else {
gm.Run(func() {
fib1 := newFibonacci(n-1, gm)
c2 <- fib1.answer
})
gm.Run(func() {
fib2 := newFibonacci(n-2, gm)
c1 <- fib2.answer
})
f.answer = <-c2 + <-c1
}
close(c1)
close(c2)
return f
}
func main() {
numbers := float64{30, 35, 36, 37, 38, 39, 40} //{30, 35, 36, 37, 38, 39, 40}
for _, value := range numbers {
start := time.Now()
fmt.Println("getting the ", value, " fibonacci number")
gm := NewGoRoutineManager(3)
f := newFibonacci(value, gm)
fmt.Println(f.answer)
end := time.Now()
totalTime := end.Sub(start)
fmt.Println("Fibonacci number: ", value, " took ", totalTime, "n")
}
}
answered Nov 5 at 12:17
nightfury1204
43025
43025
add a comment |
add a comment |
Swade is a new contributor. Be nice, and check out our Code of Conduct.
Swade is a new contributor. Be nice, and check out our Code of Conduct.
Swade is a new contributor. Be nice, and check out our Code of Conduct.
Swade is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53147240%2fnth-fibonacci-number-in-go-using-recursion-and-concurrency%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
You have a combinatorial explodion: cs.toronto.edu/~gfb/csc104/2016W/Lectures/…
– peterSO
Nov 5 at 2:24
"supposed to be very efficient" and then "recursive fibonacci implementation", these two doesn't go together, period. An efficient fibonacci implementation uses a loop, and isn't recursive. The recursive variant is only good for one thing and that is teaching about the pitfalls of recursion.
– Lasse Vågsæther Karlsen
Nov 5 at 12:20
"supposed to be very inefficient" and I am using this to teach the pitfalls. I'm hoping to implement a worker pool and limit the amount of workers to the number of available CPUs. I would just like to get this working to show the differences.
– Swade
Nov 5 at 17:15