2017-02-28 3 views
0

imは画像をセグメントに分解して操作するアルゴリズムを記述していますが、現在Goルーチンを使用している方法は最適ではありません。ワーカープールでGOルーチンを送信する方法

私はそれをワーカープールに分割し、ルーチンを起動し、各作業者に画像が完成するまで新しい仕事をさせたいと思います。

私はそれのような8に分かれてあります。私は、Goは、私は労働者のシステムにこれを最適化する方法を次々と、ルーチンオフ火災

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

答えは、最も確実にバッファされたチャネルです。あなたがそれを経験していないなら、go tourは同時並行プリミティブをかなりうまく説明します。 https://tour.golang.org/concurrency/2 – Gant

答えて

2

あなたは労働者の数、すなわち、(n個の部分に作業を分割する画像分割の上に、呼び出し元に制御を与える同時イメージプロセッサを実装するためと実行の並行処理レベルを超える一般的なパターンを持っています(おそらく異なる)数の処理ジョブを実行するために使用されるゴルーチン。

前者は上で動作するn個の画像のパーティションを返すジョブを取るFUNCされ、後者は、処理のために使用されるFUNCである、PartitionerProcessorを取るパターン全体を実装pprocess 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) 
    } 
} 
関連する問題