Skip to content

Instantly share code, notes, and snippets.

@suzuken
Last active April 6, 2016 02:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save suzuken/0097b1f43f725013d871ec19a1ca87f6 to your computer and use it in GitHub Desktop.
Save suzuken/0097b1f43f725013d871ec19a1ca87f6 to your computer and use it in GitHub Desktop.
package main
import (
"flag"
"image"
"image/color"
"image/png"
"log"
"math/cmplx"
"os"
"sync"
)
type Pixel struct {
x, y int
z color.Color
}
// bound is helper func for caliculate adaptive range.
func bound(i, given, all int) (from, to int) {
if i < 0 {
return 0, 0
}
if i >= all {
panic("i should be lower than all")
}
return i * given / all, (i+1)*given/all - 1
}
func main() {
const (
xmin, ymin, xmax, ymax = -2, -2, +2, +2
)
var (
concurrency = flag.Int("concurrency", 2, "go go go (number of goroutine)")
width = flag.Int("width", 1024, "width")
height = flag.Int("height", 1024, "height")
)
flag.Parse()
var wg sync.WaitGroup
ch := make(chan Pixel, (*height)*(*width))
for i := 0; i < *concurrency; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
from, to := bound(i, *height, *concurrency)
for py := from; py <= to; py++ {
y := float64(py)/float64(*height)*(ymax-ymin) + ymin
for px := 0; px < *width; px++ {
// Image point (px, py) represents complex value z.
x := float64(px)/float64(*width)*(xmax-xmin) + xmin
z := complex(x, y)
ch <- Pixel{px, py, mandelbrot(z)}
}
}
}(i)
}
go func() {
wg.Wait()
close(ch)
}()
img := image.NewRGBA(image.Rect(0, 0, *width, *height))
for p := range ch {
img.Set(p.x, p.y, p.z)
}
if err := png.Encode(os.Stdout, img); err != nil {
log.Fatalf("encode failed %s", err)
}
}
func mandelbrot(z complex128) color.Color {
const iterations = 200
const contrast = 15
var v complex128
for n := uint8(0); n < iterations; n++ {
v = v*v + z
if cmplx.Abs(v) > 2 {
return color.Gray{255 - contrast*n}
}
}
return color.Black
}
//!-
// Some other interesting functions:
func acos(z complex128) color.Color {
v := cmplx.Acos(z)
blue := uint8(real(v)*128) + 127
red := uint8(imag(v)*128) + 127
return color.YCbCr{192, blue, red}
}
func sqrt(z complex128) color.Color {
v := cmplx.Sqrt(z)
blue := uint8(real(v)*128) + 127
red := uint8(imag(v)*128) + 127
return color.YCbCr{128, blue, red}
}
// f(x) = x^4 - 1
//
// z' = z - f(z)/f'(z)
// = z - (z^4 - 1) / (4 * z^3)
// = z - (z - 1/z^3) / 4
func newton(z complex128) color.Color {
const iterations = 37
const contrast = 7
for i := uint8(0); i < iterations; i++ {
z -= (z - 1/(z*z*z)) / 4
if cmplx.Abs(z*z*z*z-1) < 1e-6 {
return color.Gray{255 - contrast*i}
}
}
return color.Black
}
@suzuken
Copy link
Author

suzuken commented Apr 6, 2016

-> % system_profiler SPHardwareDataType
Hardware:

    Hardware Overview:

      Model Name: MacBook Pro
      Model Identifier: MacBookPro11,2
      Processor Name: Intel Core i7
      Processor Speed: 2.6 GHz
      Number of Processors: 1
      Total Number of Cores: 4
      L2 Cache (per Core): 256 KB
      L3 Cache: 6 MB
      Memory: 16 GB
      Boot ROM Version: MBP112.0138.B16
      SMC Version (system): 2.18f6

experiment.

1024 x 1024

    -> % time go run ch8/ex5.go -concurrency 1 -width 1024 -height 1024 > m.png
    go run ch8/ex5.go -concurrency 1 -width 1024 -height 1024 > m.png  1.14s user 0.13s system 130% cpu 0.975 total
    -> % time go run ch8/ex5.go -concurrency 2 -width 1024 -height 1024 > m.png
    go run ch8/ex5.go -concurrency 2 -width 1024 -height 1024 > m.png  1.24s user 0.17s system 169% cpu 0.834 total
    -> % time go run ch8/ex5.go -concurrency 3 -width 1024 -height 1024 > m.png
    go run ch8/ex5.go -concurrency 3 -width 1024 -height 1024 > m.png  1.24s user 0.28s system 167% cpu 0.901 total
    -> % time go run ch8/ex5.go -concurrency 4 -width 1024 -height 1024 > m.png
    go run ch8/ex5.go -concurrency 4 -width 1024 -height 1024 > m.png  1.34s user 0.32s system 192% cpu 0.859 total
    -> % time go run ch8/ex5.go -concurrency 8 -width 1024 -height 1024 > m.png
    go run ch8/ex5.go -concurrency 8 -width 1024 -height 1024 > m.png  1.59s user 0.71s system 252% cpu 0.912 total
    -> % time go run ch8/ex5.go -concurrency 16 -width 1024 -height 1024 > m.png
    go run ch8/ex5.go -concurrency 16 -width 1024 -height 1024 > m.png  1.56s user 0.67s system 245% cpu 0.910 total


4096 x 4096

    -> % time go run ch8/ex5.go -concurrency 1 -width 4096 -height 4096 > m.png
    go run ch8/ex5.go -concurrency 1 -width 4096 -height 4096 > m.png  11.85s user 0.98s system 133% cpu 9.607 total
    -> % time go run ch8/ex5.go -concurrency 2 -width 4096 -height 4096 > m.png
    go run ch8/ex5.go -concurrency 2 -width 4096 -height 4096 > m.png  14.03s user 1.38s system 219% cpu 7.026 total
    -> % time go run ch8/ex5.go -concurrency 4 -width 4096 -height 4096 > m.png
    go run ch8/ex5.go -concurrency 4 -width 4096 -height 4096 > m.png  14.63s user 4.12s system 255% cpu 7.333 total
    -> % time go run ch8/ex5.go -concurrency 8 -width 4096 -height 4096 > m.png
    go run ch8/ex5.go -concurrency 8 -width 4096 -height 4096 > m.png  18.44s user 10.93s system 355% cpu 8.264 total
    -> % time go run ch8/ex5.go -concurrency 16 -width 4096 -height 4096 > m.png
    go run ch8/ex5.go -concurrency 16 -width 4096 -height 4096 > m.png  18.72s user 10.71s system 355% cpu 8.288 total

@suzuken
Copy link
Author

suzuken commented Apr 6, 2016

from gopl.io, chapter 8 ex. 5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment