如何在工作池中发送GO例程
我正在编写一个算法,将图像分割成若干段并进行操作,但是我目前使用的Go例程并不是很理想 我想将它拆分为一个工作池,启动例程,让每个工作人员执行一个新任务,直到映像完成 我将其分为8个部分:如何在工作池中发送GO例程,go,Go,我正在编写一个算法,将图像分割成若干段并进行操作,但是我目前使用的Go例程并不是很理想 我想将它拆分为一个工作池,启动例程,让每个工作人员执行一个新任务,直到映像完成 我将其分为8个部分: var bounds = img.Bounds() var halfHeight = bounds.Max.Y / 2 var eighthOne = halfHeight / 4 var eighthTwo = eighthOne +
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)
然后我一个接一个地启动Go例程,如何将其优化到worker系统中
感谢您这里有一个实现并发图像处理器的通用模式,该模式允许调用方控制图像分区,将工作分成n个部分,并控制执行的并发级别(即用于执行(可能不同)数量的处理作业的工作进程数) 请参见
p进程
func,它实现了使用分区器
和处理器
的整个模式,前者是一个func,负责返回n个要操作的图像分区,后者是一个func,用于处理每个分区
我在funcsplitVert
中实现了代码示例中表示的垂直分割,该函数返回一个函数,该函数可以将图像分割为n个垂直部分
为了完成一些实际工作,我实现了gray
func,它是一个处理器,可以将像素颜色转换为灰度(亮度)
以下是工作代码:
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)
}
}
类型可变图像接口{
图像,图像
集合(x,y int,c color.color)
}
类型处理器func(可变图像,图像.矩形)
键入Partitioner func(image.image)[]image.Rectangle
FuncPProcess(i image.image、并发int、部分分区器、过程处理器)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,并发*2)
对于n:=0;n c这里有一个通用模式,用于实现并发图像处理器,通过图像分区控制调用方将工作分成n个部分,并控制执行的并发级别(即用于执行(可能不同)数量的处理作业的工作进程数)
请参见p进程
func,它实现了使用分区器
和处理器
的整个模式,前者是一个func,负责返回n个要操作的图像分区,后者是一个func,用于处理每个分区
我在funcsplitVert
中实现了代码示例中表示的垂直分割,该函数返回一个函数,该函数可以将图像分割为n个垂直部分
为了完成一些实际工作,我实现了gray
func,它是一个处理器,可以将像素颜色转换为灰度(亮度)
以下是工作代码:
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)
}
}
类型可变图像接口{
图像,图像
集合(x,y int,c color.color)
}
类型处理器func(可变图像,图像.矩形)
键入Partitioner func(image.image)[]image.Rectangle
FuncPProcess(i image.image、并发int、部分分区器、过程处理器)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,并发*2)
对于n:=0;n c看答案是最确定的缓冲通道。如果你没有看过,go tour会很好地解释go并发原语。看答案是最确定的缓冲通道。如果你没有看过,go tour会很好地解释go并发原语。