2017-02-28 111 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) 
    } 
}