Julia set image rendering ruined by concurrency - image

I have the following code that I am to change into a concurrent program.
// Stefan Nilsson 2013-02-27
// This program creates pictures of Julia sets (en.wikipedia.org/wiki/Julia_set).
package main
import (
"image"
"image/color"
"image/png"
"log"
"math/cmplx"
"os"
"strconv"
)
type ComplexFunc func(complex128) complex128
var Funcs []ComplexFunc = []ComplexFunc{
func(z complex128) complex128 { return z*z - 0.61803398875 },
func(z complex128) complex128 { return z*z + complex(0, 1) },
}
func main() {
for n, fn := range Funcs {
err := CreatePng("picture-"+strconv.Itoa(n)+".png", fn, 1024)
if err != nil {
log.Fatal(err)
}
}
}
// CreatePng creates a PNG picture file with a Julia image of size n x n.
func CreatePng(filename string, f ComplexFunc, n int) (err error) {
file, err := os.Create(filename)
if err != nil {
return
}
defer file.Close()
err = png.Encode(file, Julia(f, n))
return
}
// Julia returns an image of size n x n of the Julia set for f.
func Julia(f ComplexFunc, n int) image.Image {
bounds := image.Rect(-n/2, -n/2, n/2, n/2)
img := image.NewRGBA(bounds)
s := float64(n / 4)
for i := bounds.Min.X; i < bounds.Max.X; i++ {
for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
n := Iterate(f, complex(float64(i)/s, float64(j)/s), 256)
r := uint8(0)
g := uint8(0)
b := uint8(n % 32 * 8)
img.Set(i, j, color.RGBA{r, g, b, 255})
}
}
return img
}
// Iterate sets z_0 = z, and repeatedly computes z_n = f(z_{n-1}), n ≥ 1,
// until |z_n| > 2 or n = max and returns this n.
func Iterate(f ComplexFunc, z complex128, max int) (n int) {
for ; n < max; n++ {
if real(z)*real(z)+imag(z)*imag(z) > 4 {
break
}
z = f(z)
}
return
}
I have decided to try and make the Julia() function concurrent. So I changed it to:
func Julia(f ComplexFunc, n int) image.Image {
bounds := image.Rect(-n/2, -n/2, n/2, n/2)
img := image.NewRGBA(bounds)
s := float64(n / 4)
for i := bounds.Min.X; i < bounds.Max.X; i++ {
for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
go func(){
n := Iterate(f, complex(float64(i)/s, float64(j)/s), 256)
r := uint8(0)
g := uint8(0)
b := uint8(n % 32 * 8)
img.Set(i, j, color.RGBA{r, g, b, 255})
}()
}
}
return img
This change causes the images to look very different. The patterns are essentially the same, but there are a lot of white pixels that were not there before.
What is happening here?

There are 2 problems:
You don't actually wait for your goroutines to finish.
You don't pass i and j to the goroutine, so they will almost always be the last i and j.
Your function should look something like:
func Julia(f ComplexFunc, n int) image.Image {
var wg sync.WaitGroup
bounds := image.Rect(-n/2, -n/2, n/2, n/2)
img := image.NewRGBA(bounds)
s := float64(n / 4)
for i := bounds.Min.X; i < bounds.Max.X; i++ {
for j := bounds.Min.Y; j < bounds.Max.Y; j++ {
wg.Add(1)
go func(i, j int) {
n := Iterate(f, complex(float64(i)/s, float64(j)/s), 256)
r := uint8(0)
g := uint8(0)
b := uint8(n % 32 * 8)
img.Set(i, j, color.RGBA{r, g, b, 255})
wg.Done()
}(i, j)
}
}
wg.Wait()
return img
}
A bonus tip, when diving into concurrency, it's usually a good idea to try your code with the race detector.
You might have to use a mutex to call img.Set but I'm not very sure and I can't test atm.

Related

Concurrent QuickSort only partially sorting

im trying to implement QuickSort concurrently. When I run it and look at the sorted array, there is a portion of elements near the start of the array that is unsorted but the majority of the array is.
Code Below
package main
import (
"fmt"
"math/rand"
//"runtime"
"sync"
"time"
)
func main() {
slice := generateSlice(1000000)
var wg sync.WaitGroup
start := time.Now()
go Quicksort(slice, 0, len(slice)-1, &wg)
wg.Wait()
end := time.Since(start)
fmt.Printf("Sort Time: %v, sorted: %v \n", end, slice)
}
func Quicksort(A []int, p int, r int, wg *sync.WaitGroup) {
if p < r {
q := Partition(A, p, r)
wg.Add(2)
go Quicksort(A, p, q-1, wg)
go Quicksort(A, q+1, r, wg)
}
}
func Partition(A []int, p int, r int) int {
index := rand.Intn(r-p) + p
pivot := A[index]
A[index] = A[r]
A[r] = pivot
x := A[r]
j := p - 1
i := p
for i < r {
if A[i] <= x {
j++
tmp := A[j]
A[j] = A[i]
A[i] = tmp
}
i++
}
temp := A[j+1]
A[j+1] = A[r]
A[r] = temp
return j + 1
}
func generateSlice(size int) []int {
slice := make([]int, size)
rand.Seed(time.Now().UnixNano())
for i := 0; i < size; i++ {
slice[i] = rand.Intn(999) - rand.Intn(999)
}
return slice
}
I can't seem to find the issue, any ideas?
Your implementation has multiple problems. Hymns For Disco has already mentioned a couple of them in the comments. Another change I would suggest is not to use the same waitGroup in all recursive function calls. It can be very difficult to keep track of counter increments and decrements and you might reach a deadlock.
I have made a few changes to your code. I think it's working fine. Note that 'Partition' and 'generateSlice' functions remain unchanged.
func main() {
slice := generateSlice(1000)
Quicksort(slice, 0, len(slice)-1)
fmt.Printf("%v\n", slice)
}
func Quicksort(A []int, p int, r int) {
if p < r {
var wg sync.WaitGroup
q := Partition(A, p, r)
wg.Add(2)
go func() {
defer wg.Done()
Quicksort(A, p, q-1)
}()
go func() {
defer wg.Done()
Quicksort(A, q+1, r)
}()
wg.Wait()
}
}

How to collect values from a channel into a slice in Go?

Suppose I have a helper function helper(n int) which returns a slice of integers of variable length. I would like to run helper(n) in parallel for various values of n and collect the output in one big slice. My first attempt at this is the following:
package main
import (
"fmt"
"golang.org/x/sync/errgroup"
)
func main() {
out := make([]int, 0)
ch := make(chan int)
go func() {
for i := range ch {
out = append(out, i)
}
}()
g := new(errgroup.Group)
for n := 2; n <= 3; n++ {
n := n
g.Go(func() error {
for _, i := range helper(n) {
ch <- i
}
return nil
})
}
if err := g.Wait(); err != nil {
panic(err)
}
close(ch)
// time.Sleep(time.Second)
fmt.Println(out) // should have the same elements as [0 1 0 1 2]
}
func helper(n int) []int {
out := make([]int, 0)
for i := 0; i < n; i++ {
out = append(out, i)
}
return out
}
However, if I run this example I do not get all 5 expected values, instead I get
[0 1 0 1]
(If I uncomment the time.Sleep I do get all five values, [0 1 2 0 1], but this is not an acceptable solution).
It seems that the problem with this is that out is being updated in a goroutine, but the main function returns before it is done updating.
One thing that would work is using a buffered channel of size 5:
func main() {
ch := make(chan int, 5)
g := new(errgroup.Group)
for n := 2; n <= 3; n++ {
n := n
g.Go(func() error {
for _, i := range helper(n) {
ch <- i
}
return nil
})
}
if err := g.Wait(); err != nil {
panic(err)
}
close(ch)
out := make([]int, 0)
for i := range ch {
out = append(out, i)
}
fmt.Println(out) // should have the same elements as [0 1 0 1 2]
}
However, although in this simplified example I know what the size of the output should be, in my actual application this is not known a priori. Essentially what I would like is an 'infinite' buffer such that sending to the channel never blocks, or a more idiomatic way to achieve the same thing; I've read https://blog.golang.org/pipelines but wasn't able to find a close match to my use case. Any ideas?
In this version of the code, the execution is blocked until ch is closed.
ch is always closed at the end of a routine that is responsible to push into ch. Because the program pushes to ch in a routine, it is not needed to use a buffered channel.
package main
import (
"fmt"
"golang.org/x/sync/errgroup"
)
func main() {
ch := make(chan int)
go func() {
g := new(errgroup.Group)
for n := 2; n <= 3; n++ {
n := n
g.Go(func() error {
for _, i := range helper(n) {
ch <- i
}
return nil
})
}
if err := g.Wait(); err != nil {
panic(err)
}
close(ch)
}()
out := make([]int, 0)
for i := range ch {
out = append(out, i)
}
fmt.Println(out) // should have the same elements as [0 1 0 1 2]
}
func helper(n int) []int {
out := make([]int, 0)
for i := 0; i < n; i++ {
out = append(out, i)
}
return out
}
Here is the fixed version of the first code, it is convoluted but demonstrates the usage of sync.WaitGroup.
package main
import (
"fmt"
"sync"
"golang.org/x/sync/errgroup"
)
func main() {
out := make([]int, 0)
ch := make(chan int)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
for i := range ch {
out = append(out, i)
}
}()
g := new(errgroup.Group)
for n := 2; n <= 3; n++ {
n := n
g.Go(func() error {
for _, i := range helper(n) {
ch <- i
}
return nil
})
}
if err := g.Wait(); err != nil {
panic(err)
}
close(ch)
wg.Wait()
// time.Sleep(time.Second)
fmt.Println(out) // should have the same elements as [0 1 0 1 2]
}
func helper(n int) []int {
out := make([]int, 0)
for i := 0; i < n; i++ {
out = append(out, i)
}
return out
}

Change 2D slice in-place

I am implementing a matrix-matrix multiplication algorithm in Go and I cannot reason how to change the output matrix in-place. I have tried changing the input to a pointer but 2D slices cannot be pointers?
package main
import (
"fmt"
"strconv"
"math/rand"
"os"
"time"
)
func main() {
L := len(os.Args)
m, n, p, q, err := mapVars(L, os.Args)
if err != 0 {
fmt.Fprintf(os.Stderr, "error: Incorrect command line arguments.\n")
os.Exit(1)
}
fmt.Println("The product array has dimensions.")
fmt.Printf("\tC is %dx%d\n", m, q)
fmt.Println("\nPopulating matrix A.")
A, _ := createMat(m, n)
fmt.Println("Matrix A.")
printMat(m, A)
fmt.Println("\nPopulating matrix B.")
B, _ := createMat(p, q)
fmt.Println("Matrix B.")
printMat(p, B)
fmt.Println("\nPerforming row-wise matrix-matrix multiplication AB.")
startRow := time.Now()
C := rowMultMat(m, n, q, A, B)
dtRow := time.Since(startRow)
fmt.Printf("Time elapsed: %v\n", dtRow)
fmt.Println("Matrix C.")
printMat(q, C)
}
func mapVars(l int, args []string) (m int, n int, p int, q int, err int) {
if l == 2 {
m, _ := strconv.Atoi(args[1])
n, _ := strconv.Atoi(args[1])
p, _ := strconv.Atoi(args[1])
q, _ := strconv.Atoi(args[1])
fmt.Printf("Creating two arrays, A, B, with square dimensions.\n")
fmt.Printf("\tA is %dx%d\n\tB is %dx%d\n", m, n, p, q)
return m, n, p, q, 0
} else if (l == 5 || n != p) {
m, _ := strconv.Atoi(args[1])
n, _ := strconv.Atoi(args[2])
p, _ := strconv.Atoi(args[3])
q, _ := strconv.Atoi(args[4])
fmt.Println("Creating two arrays, A, B, with dimensions.")
fmt.Printf("\tA is %dx%d\n\tB is %dx%d\n", m, n, p, q)
return m, n, p, q, 0
} else {
fmt.Println("Incorrect command line arguments.\n")
return 0, 0, 0, 0, 1
}
}
func initMat(m int, n int) (M [][]float64, rows []float64) {
M = make([][]float64, m)
rows = make([]float64, n*m)
for i := 0; i < m; i++ {
M[i] = rows[i*n : (i+1)*n]
}
return M, rows
}
func createMat(m int, n int) (M [][]float64, rows []float64) {
M = make([][]float64, m)
rows = make([]float64, n*m)
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
rows[i*n + j] = float64(rand.Int63()%10)
}
M[i] = rows[i*n : (i+1)*n]
}
return M, rows
}
func printMat(row int, M [][]float64) {
for i := 0; i < row; i++ {
fmt.Printf("%v\n", M[i])
}
}
func rowMultMat(m int, n int, q int, A [][]float64, B [][]float64) (C [][]float64) {
C, _ = initMat(m, q)
var total float64 = 0.0
for i := 0; i < m; i++ {
for j := 0; j < q; j++ {
for k := 0; k < n; k++ {
total += A[i][k] * (B[k][j])
}
C[i][j] = total
total = 0
}
}
return C
}
Currently I am initializing the matrix inside rowMultMat because I am unable to pass C as a pointer to a 2D slice. For example, run main.go 2 3 3 2 will multiply a 2x3 with 3x2 to yield 2x2.
A slice is already a reference value. If you pass a slice into a function, the function can modify its contents (*) and the modifications will be visible to the caller once it returns.
Alternatively, returning a new slice is also efficient - because again, slices are just references and don't take up much memory.
(*) By contents here I mean the contents of the underlying array the slice points to. Some attributes like the slice's length cannot be changed in this way; if your function needs to make the slice longer, for example, you'll have to pass in a pointer to a slice.

How to send of GO routines in a worker pool

im writing an algorithm to break down an image into segments and manipulate it, however the way im currently using Go routines isn't quite optimal.
I'd like to split it into a worker pool, firing off routines and having each worker take a new job until the image is completed.
I have it split into 8 as such:
var bounds = img.Bounds()
var halfHeight = bounds.Max.Y / 2
var eighthOne = halfHeight / 4
var eighthTwo = eighthOne + eighthOne
var eighthThree = eighthOne + eighthTwo
var eighthFive = halfHeight + eighthOne
var eighthSix = halfHeight + eighthTwo
var eighthSeven = halfHeight + eighthThree
elapsed := time.Now()
go Threshold(pic, c2, 0, eighthOne)
go Threshold(pic, c5, eighthOne, eighthTwo)
go Threshold(pic, c6, eighthTwo, eighthThree)
go Threshold(pic, c7, eighthThree, halfHeight)
go Threshold(pic, c8, halfHeight, eighthFive)
go Threshold(pic, c9, eighthFive, eighthSix)
go Threshold(pic, c10, eighthSix, eighthSeven)
go Threshold(pic, c11, eighthSeven, bounds.Max.Y)
From which i then fire off Go routines one after another, how can i optimise this into a worker system?
Thanks
Here you have a generic pattern for implementing concurrent image processors giving control to the caller over the image partitioning to split the work in n parts and over the concurrency level of the execution (i.e. the number of worker goroutines used for executing the (possibly different) number of processing jobs).
See the pprocess func which implements the whole pattern taking a Partitioner and a Processor, the former being a func that takes the job of returning n image partitions to operate on, and the latter being a func which will be used for processing each partition.
I implemented the vertical splitting you expressed in your code example in the func splitVert which returns a function which can split an image in n vertical sections.
For doing some actual work I implemented the gray func which is a Processor that transform pixel colors to gray levels (luminance).
Here's the working code:
type MutableImage interface {
image.Image
Set(x, y int, c color.Color)
}
type Processor func(MutableImage, image.Rectangle)
type Partitioner func(image.Image) []image.Rectangle
func pprocess(i image.Image, concurrency int, part Partitioner, proc Processor) image.Image {
m := image.NewRGBA(i.Bounds())
draw.Draw(m, i.Bounds(), i, i.Bounds().Min, draw.Src)
var wg sync.WaitGroup
c := make(chan image.Rectangle, concurrency*2)
for n := 0; n < concurrency; n++ {
wg.Add(1)
go func() {
for r := range c {
proc(m, r)
}
wg.Done()
}()
}
for _, p := range part(i) {
c <- p
}
close(c)
wg.Wait()
return m
}
func gray(i MutableImage, r image.Rectangle) {
for x := r.Min.X; x <= r.Max.X; x++ {
for y := r.Min.Y; y <= r.Max.Y; y++ {
c := i.At(x, y)
r, g, b, _ := c.RGBA()
l := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
i.Set(x, y, color.Gray{uint8(l / 256)})
}
}
}
func splitVert(c int) Partitioner {
return func(i image.Image) []image.Rectangle {
b := i.Bounds()
s := float64(b.Dy()) / float64(c)
rs := make([]image.Rectangle, c)
for n := 0; n < c; n++ {
m := float64(n)
x0 := b.Min.X
y0 := b.Min.Y + int(0.5+m*s)
x1 := b.Max.X
y1 := b.Min.Y + int(0.5+(m+1)*s)
if n < c-1 {
y1--
}
rs[n] = image.Rect(x0, y0, x1, y1)
}
return rs
}
}
func main() {
i, err := jpeg.Decode(os.Stdin)
if err != nil {
log.Fatalf("decoding image: %v", err)
}
o := pprocess(i, runtime.NumCPU(), splitVert(8), gray)
err = jpeg.Encode(os.Stdout, o, nil)
if err != nil {
log.Fatalf("encoding image: %v", err)
}
}

Is this a reasonable and idiomatic GoLang circular shift implementation?

Can anyone comment on whether this is a reasonable and idiomatic way of implementing circular shift of integer arrays in Go? (I deliberately chose not to use bitwise operations.)
How could it be improved?
package main
import "fmt"
func main() {
a := []int{1,2,3,4,5,6,7,8,9,10}
fmt.Println(a)
rotateR(a, 5)
fmt.Println(a)
rotateL(a, 5)
fmt.Println(a)
}
func rotateL(a []int, i int) {
for count := 1; count <= i; count++ {
tmp := a[0]
for n := 1;n < len(a);n++ {
a[n-1] = a[n]
}
a[len(a)-1] = tmp
}
}
func rotateR(a []int, i int) {
for count := 1; count <= i; count++ {
tmp := a[len(a)-1]
for n := len(a)-2;n >=0 ;n-- {
a[n+1] = a[n]
}
a[0] = tmp
}
}
Rotating the slice one position at a time, and repeating to get the total desired rotation means it will take time proportional to rotation distance × length of slice. By moving each element directly into its final position you can do this in time proportional to just the length of the slice.
The code for this is a little more tricky than you have, and you’ll need a GCD function to determine how many times to go through the slice:
func gcd(a, b int) int {
for b != 0 {
a, b = b, a % b
}
return a
}
func rotateL(a []int, i int) {
// Ensure the shift amount is less than the length of the array,
// and that it is positive.
i = i % len(a)
if i < 0 {
i += len(a)
}
for c := 0; c < gcd(i, len(a)); c++ {
t := a[c]
j := c
for {
k := j + i
// loop around if we go past the end of the slice
if k >= len(a) {
k -= len(a)
}
// end when we get to where we started
if k == c {
break
}
// move the element directly into its final position
a[j] = a[k]
j = k
}
a[j] = t
}
}
Rotating a slice of size l right by p positions is equivalent to rotating it left by l − p positions, so you can simplify your rotateR function by using rotateL:
func rotateR(a []int, i int) {
rotateL(a, len(a) - i)
}
Your code is fine for in-place modification.
Don't clearly understand what you mean by bitwise operations. Maybe this
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
fmt.Println(a)
rotateR(&a, 4)
fmt.Println(a)
rotateL(&a, 4)
fmt.Println(a)
}
func rotateL(a *[]int, i int) {
x, b := (*a)[:i], (*a)[i:]
*a = append(b, x...)
}
func rotateR(a *[]int, i int) {
x, b := (*a)[:(len(*a)-i)], (*a)[(len(*a)-i):]
*a = append(b, x...)
}
Code works https://play.golang.org/p/0VtiRFQVl7
It's called reslicing in Go vocabulary. Tradeoff is coping and looping in your snippet vs dynamic allocation in this. It's your choice, but in case of shifting 10000 elements array by one position reslicing looks much cheaper.
I like Uvelichitel solution but if you would like modular arithmetic which would be O(n) complexity
package main
func main(){
s := []string{"1", "2", "3"}
rot := 5
fmt.Println("Before RotL", s)
fmt.Println("After RotL", rotL(rot, s))
fmt.Println("Before RotR", s)
fmt.Println("After RotR", rotR(rot,s))
}
func rotL(m int, arr []string) []string{
newArr := make([]string, len(arr))
for i, k := range arr{
newPos := (((i - m) % len(arr)) + len(arr)) % len(arr)
newArr[newPos] = k
}
return newArr
}
func rotR(m int, arr []string) []string{
newArr := make([]string, len(arr))
for i, k := range arr{
newPos := (i + m) % len(arr)
newArr[newPos] = k
}
return newArr
}
If you need to enter multiple values, whatever you want (upd code Uvelichitel)
package main
import "fmt"
func main() {
var N, n int
fmt.Scan(&N)
a := make([]int, N)
for i := 0; i < N; i++ {
fmt.Scan(&a[i])
}
fmt.Scan(&n)
if n > 0 {
rotateR(&a, n%len(a))
} else {
rotateL(&a, (n*-1)%len(a))
}
for _, elem := range a {
fmt.Print(elem, " ")
}
}
func rotateL(a *[]int, i int) {
x, b := (*a)[:i], (*a)[i:]
*a = append(b, x...)
}
func rotateR(a *[]int, i int) {
x, b := (*a)[:(len(*a)-i)], (*a)[(len(*a)-i):]
*a = append(b, x...)
}

Resources