2017-02-28 112 views
0

即时编写算法将图片分解成段并对其进行处理,但是目前使用Go例程的方式并不十分理想。如何在工作池中发送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) 

从中我再断火转到例程此起彼伏,如何优化到这个工人的系统?

感谢

+2

参见[?这是围棋的习惯工作者线程池(http://stackoverflow.com/questions/38170852/is-this-an-idiomatic-worker -thread-pool-in-go/38172204#38172204) – icza

+0

答案肯定是缓冲的渠道。如果你还没有经历它,那么去巡视就会很好地解释并发原语。 https://tour.golang.org/concurrency/2 – Gant

回答

2

这里有实现并行图像处理器将控制权给呼叫者在图像分割中的n个部分,并通过执行的并发级别(拆分工作,即工人数量的通用模式用于执行(可能不同)数量的处理工作的goroutines)。

参见pprocess FUNC它实现了整个图案采取PartitionerProcessor,前者是一个FUNC即需要返回N个图像的分区上操作的作业,而后者是将被用于处理的FUNC每个分区。

我在func splitVert中实现了你在代码示例中表达的垂直分割,该函数返回一个函数,该函数可以在n个垂直剖面中分割图像。

为了做一些实际工作,我实现了gray func,它是一个Processor,它将像素颜色转换为灰度级(亮度)。

这里的工作代码:

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) 
    } 
}