8

プッシュ機能とポップ機能を持つキュー構造体を作成しようとしています。

以下のコードで行ったように、10 スレッドのプッシュと別の 10 スレッドのデータのポップを使用する必要があります。

質問:

  1. プッシュ/ポップした量を印刷する必要がありますが、その方法がわかりません。
  2. とにかくコードを高速化する方法はありますか? コードは私には遅すぎます。
package main

import (
    "runtime"
    "time"
)

const (
    DATA_SIZE_PER_THREAD = 10000000
)

type Queue struct {
    records string
}


func (self Queue) push(record chan interface{}) {
    // need push counter
    record <- time.Now()
}

func (self Queue) pop(record chan interface{}) {
    // need pop counter
    <- record
}

func main() {
    runtime.GOMAXPROCS(runtime.NumCPU())
    //record chan
    record := make(chan interface{},1000000)
    //finish flag chan
    finish := make(chan bool)
    queue := new(Queue)
    for i:=0; i<10; i++ {
        go func() {
            for j:=0; j<DATA_SIZE_PER_THREAD; j++ {
                queue.push(record)
            }
            finish<-true
        }()
    }
    for i:=0; i<10; i++ {
        go func() {
            for j:=0; j<DATA_SIZE_PER_THREAD; j++ {
                queue.pop(record)
            }
            finish<-true
        }()
    }
    for i:=0; i<20; i++ {
        <-finish
    }
}
4

2 に答える 2

15

修正すべき点がいくつかあります。

  • Queue 型のメソッドには、ポインター レシーバーが必要です。そうしないと、すべてのメソッド呼び出しで現在のキュー タイプのコピーが作成され、キュー フィールドへの変更はメソッド呼び出し自体を超えて保持されません。

  • すべてのルーチンが終了するのを待つには、sync.WaitGroup. これは、特にそのために設計されたものです。

  • sync/atomicパッケージを使用すると、キュー タイプ内でスレッド セーフなプッシュ/ポップ カウンターを維持できます。

速度に関する限り、あなたの例から、あなたが何を達成しようとしているのかよくわかりません。少し詳しく説明すると、最適化が行われる可能性があります。

コードから変更した例を次に示します。

package main

import (
    "log"
    "runtime"
    "sync"
    "sync/atomic"
    "time"
)

const SizePerThread = 10000000

type Queue struct {
    records string
    count   int64
}

func (q *Queue) push(record chan interface{}) {
    record <- time.Now()

    newcount := atomic.AddInt64(&q.count, 1)
    log.Printf("Push: %d", newcount)
}

func (q *Queue) pop(record chan interface{}) {
    <-record

    newcount := atomic.AddInt64(&q.count, -1)
    log.Printf("Pop: %d", newcount)
}

func main() {
    var wg sync.WaitGroup

    runtime.GOMAXPROCS(runtime.NumCPU())

    record := make(chan interface{}, 1000000)
    queue := new(Queue)

    // We are launching 20 goroutines.
    // Let the waitgroup know it should wait for as many
    // of them to finish.
    wg.Add(20)

    for i := 0; i < 10; i++ {
        go func() {
            defer wg.Done()

            for j := 0; j < SizePerThread; j++ {
                queue.push(record)
            }
        }()

        go func() {
            defer wg.Done()

            for j := 0; j < SizePerThread; j++ {
                queue.pop(record)
            }
        }()
    }

    // Wait for all goroutines to finish.
    wg.Wait()
}
于 2012-09-04T15:37:20.453 に答える
-5

質問1への回答:jimtが示唆しているように、sync / atomicには、カウンターをアトミックに更新するための関数があります。これは便利な場合があります。

質問2への回答:DATA_SIZE_PER_THREADの値を減らすか、さらに良いことに、プログラムを使用してください

package main
func main() {}

これにより、プログラムと同じ出力がより効率的に生成されます。

真剣に、しかし、私はあなたがいくつかの概念を探求するための小さなプログラムを書いたことを理解しています。ただし、プログラムには多くの問題が含まれています。今はスピードを心配する時ではなく、いくつかの基本的な概念を学ぶ時です。

于 2012-09-09T20:18:46.567 に答える