如何在工作池中发送GO例程

如何在工作池中发送GO例程,go,Go,我正在编写一个算法,将图像分割成若干段并进行操作,但是我目前使用的Go例程并不是很理想 我想将它拆分为一个工作池,启动例程,让每个工作人员执行一个新任务,直到映像完成 我将其分为8个部分: var bounds = img.Bounds() var halfHeight = bounds.Max.Y / 2 var eighthOne = halfHeight / 4 var eighthTwo = eighthOne +

我正在编写一个算法,将图像分割成若干段并进行操作,但是我目前使用的Go例程并不是很理想

我想将它拆分为一个工作池,启动例程,让每个工作人员执行一个新任务,直到映像完成

我将其分为8个部分:

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,用于处理每个分区

我在func
splitVert
中实现了代码示例中表示的垂直分割,该函数返回一个函数,该函数可以将图像分割为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;nc这里有一个通用模式,用于实现并发图像处理器,通过图像分区控制调用方将工作分成n个部分,并控制执行的并发级别(即用于执行(可能不同)数量的处理作业的工作进程数)

请参见
p进程
func,它实现了使用
分区器
处理器
的整个模式,前者是一个func,负责返回n个要操作的图像分区,后者是一个func,用于处理每个分区

我在func
splitVert
中实现了代码示例中表示的垂直分割,该函数返回一个函数,该函数可以将图像分割为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;nc看答案是最确定的缓冲通道。如果你没有看过,go tour会很好地解释go并发原语。看答案是最确定的缓冲通道。如果你没有看过,go tour会很好地解释go并发原语。