How channel work in using channel to find prime number problem? - go

I have an approach to solve the find prime number problem using Go like this:
package main
import (
"fmt"
)
// Generate natural seri number: 2,3,4,...
func GenerateNatural() chan int {
ch := make(chan int)
go func() {
for i := 2; ; i++ {
ch <- i
}
}()
return ch
}
// Filter: delete the number which is divisible by a prime number to find prime number
func PrimeFilter(in <-chan int, prime int) chan int {
out := make(chan int)
go func() {
for {
if i := <-in; i%prime != 0 {
out <- i
}
}
}()
return out
}
func main() {
ch := GenerateNatural()
for i := 0; i < 100; i++ {
prime := <-ch
fmt.Printf("%v: %v\n", i+1, prime)
ch = PrimeFilter(ch, prime)
}
}
I have no idea what happen in this approach:
I know that can not print the content of channel without interrupt: Can not print content of channel
Size of channel: Default buffer channel size is 1, that mean:
By default channels are unbuffered, which states that they will only
accept sends (chan <-) if there is a corresponding receive (<- chan)
which are ready to receive the sent value
I can not image how above Go program run!
Could anybody please help to show me the step by step flow of above Go program for first 10 number or so?

This is a pretty convoluted example. In both functions, go func(){...}() creates an anonymous goroutine and runs it asynchronously, then returns the channel which will receive values from the goroutine. PrimeFilter returns a channel which will receive numbers not divisible by a certain candidate.
The idea is that prime := <-ch always takes the first element from the channel. So, to visualize the flow:
GenerateNatural() starts by sending numbers 2, 3, 4... to ch.
First loop iteration:
a. prime := <-ch reads the first (prime) number 2.
b. PrimeFilter(ch, 2) then continues receiving the rest of the numbers (3, 4, 5, ...), and sends numbers not divisible by 2 to the output channel. So, channel returned by PrimeFilter(ch, 2) will receive numbers (3, 5, 7, ...).
c. ch = PrimeFilter(ch, prime) in the main function now replaces the local ch variable with the output of PrimeFilter(ch, 2) from the previous step.
Second loop iteration:
a. prime := <-ch reads the first (prime) number from the current ch instance (this first number is 3).
b. PrimeFilter(ch, 3) then continues receiving the (already filtered) numbers, except for the first one (so, 5, 7, 9, ...), and sends numbers not divisible by 3 to the output channel. So, channel returned by PrimeFilter(ch, 2) will receive numbers 5, 7, 11, ..., because 9 is divisible by 3.
c. ch = PrimeFilter(ch, prime) in the main function now replaces the local ch variable with the output of PrimeFilter(ch, 3) from the previous step.
...

Related

Range for loop over an unBuffered Channel

I'm new to golang and going over the gotour. I have following code which works perfectly as it should.
package main
import (
"fmt"
)
func fibonacci(n int, c chan int) {
x, y := 0, 1
for i := 0; i < n; i++ {
c <- x
x, y = y, x+y
}
close(c)
}
func main() {
c := make(chan int, 5)
// c := make(chan int) //doesn't work, why ?
go fibonacci(cap(c), c)
for i := range c {
fmt.Println(i)
}
}
But when I use an unbuffered channel instead of a buffered one, I don't get any output, why's that so ?
When you pass cap(c) through to the fibonacci function, what value is passed through? on the buffered channel the n == 5, on the unbuffered channel n == 0
and your for loop
for i := 0; i < 0; i++ {
Actually, this is a really bad way of handling the situation. You are requiring the number of channels to be equal to the number of iterations.
Using a channel in this way I would not recommend, think of the channel as being able to operate concurrently, which is not something you would want to do in this scenario!
If you pass the number in separately to the number of routines, then the unbuffered channel will work as expected:
https://play.golang.org/p/G1b2vjTUCsV
cap(c) will be zero if channel is un-buffered . See the modified program

how to understand the "ch=ch1" in the following codes?

I cannot understand the meaning of "ch=ch1" and why does it can print the prime number? does someone can explain it for me? I am learning the Go.
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.package main
package main
import "fmt"
// Send the sequence 2, 3, 4, ... to channel 'ch'.
func generate(ch chan int) {
for i := 2; ; i++ {
ch <- i // Send 'i' to channel 'ch'.
}
}
// Copy the values from channel 'in' to channel 'out',
// removing those divisible by 'prime'.
func filter(in, out chan int, prime int) {
for {
i := <-in // Receive value of new variable 'i' from 'in'.
if i%prime != 0 {
out <- i // Send 'i' to channel 'out'.
}
}
}
// The prime sieve: Daisy-chain filter processes together.
func main() {
ch := make(chan int) // Create a new channel.
go generate(ch) // Start generate() as a goroutine.
for {
prime := <-ch
fmt.Print(prime, " ")
ch1 := make(chan int)
go filter(ch, ch1, prime)
ch = ch1
}
}
could someoen explain these code for me? I have been learnt the Go for serveral days.
ch is the "current channel". The loop is the following:
You starting with the channel filled by generate. It's the channel of all integers. First number from this channel is 2 (prime number).
Then you create ch1 which is the channel of all integers without numbers divisible by 2.
= is the assignment operator. By using ch = ch1 you're telling that current channel is the channel of all integers without divisible by 2.
New loop iteration. First number from current channel is 3. You creating ch1 as current channel without numbers divisible by 3.
Assign ch1 to be current channel. So now current channel is channel of all numbers without divisible by 2 without divisible by 3.
Repeat

Wait for a buffered channel to be full

I must have missed something because I haven't found the answer online for this pretty basic problem. I am using a buffered channel capable of holding three int values.
I am then using three goroutines to fill it up and I want to do an operation once the buffered channel is full.
Here is a snippet explaining the problem:
func main() {
// Initialization of the slice a and 0 < n < len(a) - 1.
difs := make(chan int, 3)
go routine(a[:n], difs)
go routine(a[n + 1:], difs)
go routine(a[n - 1:n + 1], difs)
fmt.Println(<-difs) // Display the first result returned by one of the routine.
}
func routine(a []int, out chan<- int) {
// Long computation.
out <- result
}
I would like to update my code so that fmt.Println(<-difs) displays an array of int when all the values have been computed. I could use three times <-difs but I wonder if Go offers something cleaner to do that.
Wait using channel itself, like this working sample code:
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} // Initialization of the slice a and 0 < n < len(a) - 1.
difs := make(chan int, 3)
go routine(a[0:4], difs)
go routine(a[4:8], difs)
go routine(a[8:12], difs)
result := []int{<-difs, <-difs, <-difs}
fmt.Println(result) // Display the first result returned by one of the routine.
}
func routine(a []int, out chan<- int) {
result := 0 // Long computation.
for _, v := range a {
result += v
}
out <- result
}
output:
[10 42 26]
The function len() supports channels, returning the number of unread queued elements within the channel. However, you'll have to run a loop to periodically check it.
The traditional method of handling this is using a sync.WaitGroup, as so:
func main() {
// Initialization of the slice a and 0 < n < len(a) - 1.
var wg sync.WaitGroup
wg.Add(3)
difs := make(chan int, 3)
go routine(a[:n], difs, &wg)
go routine(a[n + 1:], difs, &wg)
go routine(n - 1:n + 1], difs, &wg)
wg.Wait() // blocks until wg.Done() is called 3 times
fmt.Println(<-difs) // Display the first result returned by one of the routine.
}
// NOTE: This MUST accept a POINTER to the waitgroup. They are not copy-safe.
func routine(a []int, out chan<- int, wg *sync.WaitGroup) {
defer wg.Done()
// Long computation.
out <- result
}

Using Go channels to speed up for loop

I'm trying to use Go's concurrency to speed up my code,
Here's what I have:
for i:=7; i>-1; i-- {
go func (ch chan int32, ch2 chan int32, i int, arx int32, ary int32, dirf []int8, dirg []int8) {
nx := arx + int32(dirf[i])
ny := ary + int32(dirg[i])
ch <- nx
ch2 <- ny
}(ch, ch2, i, arx,ary,dirf,dirg)
}
for i:=7; i>-1; i-- {
nxx := <- ch
nyx := <- ch2
ind := nyx*w+nxx
if imData[ind] == e[i]{
process[c]=nxx
process[c+1]=nyx
c+=2
matrix[ind]=1
}
}
After running this I'm not getting the matrix slice that I expected, it's full of zeros.
But if I run the code below, it gives the matrix slice just as the code without channels but it's too slow.
for i:=7; i>-1; i-- {
go func (ch chan int32, ch2 chan int32, i int, arx int32, ary int32, dirf []int8, dirg []int8) {
nx := arx + int32(dirf[i])
ny := ary + int32(dirg[i])
ch <- nx
ch2 <- ny
}(ch, ch2, i, arx,ary,dirf,dirg)
nxx := <- ch
nyx := <- ch2
ind := nyx*w+nxx
if imData[ind] == e[i]{
process[c]=nxx
process[c+1]=nyx
c+=2
matrix[ind]=1
}
}
What's wrong with the first one? Any ideas? I'm very new at Go. So, please be clear when you are suggesting something.
Edit:
I edited the code to have values in proper order,
type data struct {
i int
nx int32
ny int32
}
for i:=7; i>-1; i-- {
go func (ch chan data, i int, arx int32, ary int32, dirf []int8, dirg []int8) {
nx := arx + int32(dirf[i])
ny := ary + int32(dirg[i])
ch <- data{i,nx,ny}
}(ch, i, arx,ary,dirf,dirg)
}
for i:=7; i>-1; i-- {
d := <- ch
nxx := d.nx
nyx := d.ny
j := d.i
ind := nyx*w+nxx
if imData[ind] == e[j]{
process[c]=nxx
process[c+1]=nyx
c+=2
matrix[ind]=1
}
}
It works now but it's still too slow.
I'm trying to speed up this main code:
for i:=7; i>-1; i-- {
nx := arx + int32(dirf[i])
ny := ary + int32(dirg[i])
ind := ny*w+nx
if imData[ind] == e[i]{
process[c]=nx
process[c+1]=ny
c+=2
matrix[ind]=1
}
}
what do you suggest with that?
In the second case, you're certain that the goroutines are executed "in the right order", since you wait for goroutines to complete before you continue on to the next one.
An example would be this minimal example on the golang playground. To fix this, you probably want pass a struct of three members, your nx, ny and i values across the channel.
I'm suspecting your "if imData[ind] == e[i]" conditional is failing in the former case, but it's hard to tell without the setup code for the channels, and more details on what those various slices hold. Have you tried running it with a print statement to see what you get from the channels?
Also, note that if the channels in question are buffered, there's no guarantee that the values in ch and ch2 are going to be in the same order. This is very possibly your issue.
Goroutine 1 could put a value on ch, but Goroutine 2 could have put a value on ch2 before Goroutine 1 gets to it. If you have 7 goroutines, it's perfectly possible to see the following ordering on the channels (or any number of others):
ch: 1, 2, 3, 4, 5, 6, 7
ch2: 1, 3, 4, 5, 6, 7, 2
If they aren't buffered, this isn't possible with your code, but it's still technically unsafe (edit: actually, it still won't match up with i in the second loop). If the data is a set of ordered pairs, you should be sending each pair as a structure over a single channel.
Incidentally, you only need to pass variables to the go func() call if they are expected to change outside that call. ch, ch2, arx, ary, dirf, and dirg all appear to be effectively constant for this block of code, and thus don't need to be passed into that go func(). You only need to pass in i, because the loop changes it immediately after firing the enclosure into a goroutine.
Now, from a pure speed perspective, you're probably better off moving the first loop inside the go func() call. Instead of creating 7 goroutines while looping in the main routine, you can fire a single routine, and it will loop over the values and send them on the channels. If the channels are buffered to at least that size, this becomes a VERY fast operation. Incidentally, this also solves the issue with channel ordering (though it's still better to send ordered pairs as a structure on a single channel), since you only have a single goroutine trying to send on the channels.

What is an elegant way to shut down a chain of goroutines linked by channels?

I'm a Go learner. In order better to understand the care and feeding of channels and goroutines, I'm trying to build a Sieve of Eratosthenes as a set of goroutines connected into a pipeline by channels.
Here's what I have so far:
// esieve implements a Sieve of Eratosthenes
// as a series of channels connected together
// by goroutines
package main
import "fmt"
func sieve(mine int, inch chan int) {
start := true // First-number switch
ouch := make(chan int) // Output channel for this instance
fmt.Printf("%v\n", mine) // Print this instance's prime
for next := <-inch; next > 0; next = <-inch { // Read input channel
fmt.Printf("%v <- %v\n",mine,next) // (Trace)
if (next % mine) > 0 { // Divisible by my prime?
if start { // No; is it the first number through?
go sieve(next, ouch) // First number - create instance for it
start = false // First time done
} else { // Not first time
ouch <- next // Pass it to the next instance
}
}
}
}
func main() {
lim := 30 // Let's do up to 30
fmt.Printf("%v\n", 2) // Treat 2 as a special case
ouch := make(chan int) // Create the first segment of the pipe
go sieve(3, ouch) // Create the instance for '3'
for prime := 3; prime < lim; prime += 2 { // Generate 3, 5, ...
fmt.Printf("Send %v\n", prime) // Trace
ouch <- prime // Send it down the pipe
}
}
And as far as it goes, it works nicely.
However, when I finish the main loop, main exits before all the numbers still in the pipeline of sieve instances have propagated down to the end.
What is the simplest, most elegant, or generally accepted way to make a main routine wait for a set of goroutines (about which it only 'knows' of the first one) to complete?
As for your title question, killing worker goroutines when you don't need them anymore:
You could use the Done idiom. Reads from a closed channel yield the zero value.
Make a new channel done. When reads from this channel succeed, the goroutines know they should quit. Close the channel in main when you have all the values you need.
Check if you can read from a channel done, and exit by returning, or read from next when that's available. This partially replaces the assignment to next in you for loop:
select {
case <-done:
return
case next = <- inch:
}
Ranging over a channel also works, since closing that channel exits the loop.
As for the reverse, your body question, waiting for a set of goroutines to finish:
Use sync.WaitGroup.
var wg sync.WaitGroup
wg.Add(goroutineCount)
And when each goroutine finishes:
wg.Done()
Or use defer:
defer wg.Done()
To wait for all of them to report as Done:
wg.Wait()
In your example, simply call wg.Add(1) when you start a new goroutine, before you call wg.Done() and return. As long as you only reach zero once, wg.Wait() works as expected, so wg.Add(1) before wg.Done.
After #izca unblocked my logjam, and after a few false starts involving deadlocks when everything finished, here's my solution working correctly:
// esieve implements a Sieve of Eratosthenes
// as a series of channels connected together
// by goroutines
package main
import "fmt"
func sieve(mine int, // This instance's own prime
inch chan int, // Input channel from lower primes
done chan int, // Channel for signalling shutdown
count int) { // Number of primes - counter
start := true // First-number switch
ouch := make(chan int) // Output channel, this instance
fmt.Printf("%v ", mine) // Print this instance's prime
for next := <-inch; next > 0; next = <-inch { // Read input channel
if (next % mine) > 0 { // Divisible by my prime?
if start { // No; first time through?
go sieve(next, ouch, done, count+1) // First number,
// create instance for it
start = false // First time done
} else { // Not first time
ouch <- next // Pass to next instance
}
}
}
if start { // Just starting?
close(done) // Yes - we're last in pipe - signal done
print("\n",count," primes\n") // Number of primes/goroutines
} else {
close(ouch) // No - send the signal down the pipe
}
}
func main() {
lim := 100 // Let's do up to 100
done := make(chan int) // Create the done return channel
ouch := make(chan int) // Create the first segment of the pipe
go sieve(2, ouch, done, 1) // Create the first instance for '2'
for prime := 3; prime < lim; prime += 1 { // Generate odd numbers
ouch <- prime // Send numbers down the pipe
}
close(ouch) // Send the done signal down the pipe
<- done // and wait for it to come back
}
I'm tremendously impressed with the elegance and simplicity of Go for this kind of programming, when compared with many other languages. Of course, the warts I claim for myself.
If appropriate here, I'd welcome critical comments.

Resources