-
-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathparallel.go
69 lines (57 loc) · 1.3 KB
/
parallel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package dither
import (
"image"
"image/color"
"image/draw"
"runtime"
"sync"
)
// parallel parallelizes per-pixel image modifications, dividing the
// image up horizontally depending on the number of workers.
//
// Setting numWorkers to 0 or below will result in runtime.GOMAXPROCS(0) workers being used.
func parallel(workers int, dst draw.Image, src image.Image, f func(x, y int, c color.Color) color.Color) {
if workers <= 0 {
workers = runtime.GOMAXPROCS(0)
}
b := src.Bounds()
height := b.Dy()
worker := func(minY, maxY int) {
for y := minY; y < maxY; y++ {
for x := b.Min.X; x < b.Max.X; x++ {
dst.Set(x, y, f(x, y, src.At(x, y)))
}
}
}
if workers == 1 || height == 1 {
// Fast path for just using one worker
worker(b.Min.Y, b.Max.Y)
return
}
partSize := height / workers
if partSize == 0 {
// workers > height
workers = height
partSize = 1
}
var wg sync.WaitGroup
// Launch workers
for i := 0; i < workers; i++ {
var min, max int // Beginning and end of this part (Y axis values)
if i+1 == workers {
// Last part
// Fix off-by-one error, catch last line
min = partSize*i + b.Min.Y
max = b.Max.Y
} else {
min = partSize*i + b.Min.Y
max = partSize*(i+1) + b.Min.Y
}
wg.Add(1)
go func() {
worker(min, max)
wg.Done()
}()
}
wg.Wait()
}