Go プログラムは、ゴルーチンの数が増えると速度が低下します。これは、ゴルーチンのスケジューリングと切り替えにより追加のオーバーヘッドが発生し、プログラムのパフォーマンスが低下するためです。ゴルーチンは同時実行パフォーマンスの提供に優れていますが、ゴルーチンが多すぎるとスレッドの競合やリソースの競合が発生し、プログラムの実行効率に影響を与える可能性があります。この状況の発生を回避するには、プログラムが効率的に実行できるように、ゴルーチンの数を合理的に管理および制御する必要があります。この記事では、PHP エディターの Youzi が、Go プログラムの実行効率を向上させるために goroutine のパフォーマンスを最適化するためのいくつかの方法とテクニックを紹介します。
私は並列処理コースの小さなプロジェクトに取り組んでおり、バッファー付きチャネル、バッファーなしチャネル、スライスへのポインターを使用しないチャネルなどを使用してみました。また、(現在の状態ではなく) 可能な限り最適化しようとしましたが、それでも同じ結果が得られます。ゴルーチンの数を (1 つでも) 増やすと、プログラム全体が遅くなります。誰かが私が間違っていることを教えてもらえますか?この場合、並列性を高めることは可能でしょうか?
これはコードの一部です:
リーリー リーリーゴルーチンを増やすとプログラムの実行が速くなると予想されますが、ゴルーチンの数が一定に達すると、ゴルーチンを増やすことで実行時間は同じかわずかに遅くなります。
編集: 使用されるすべての関数:
func main() { rand.seed(time.now().unixmicro()) numagents := 2 fmt.println("please pick a number of goroutines: ") fmt.scanf("%d", &numagents) numfiles := 4 fmt.println("how many files do you want?") fmt.scanf("%d", &numfiles) start := time.now() numassist := numfiles channel := make(chan []file, numagents) files := make([]file, 0) for i := 0; i < numagents; i++ { if i == numagents-1 { go generatefiles(numassist, channel) } else { go generatefiles(numfiles/numagents, channel) numassist -= numfiles / numagents } } for i := 0; i < numagents; i++ { files = append(files, <-channel...) } elapsed := time.since(start) fmt.printf("function took %s\n", elapsed) }
簡単に言えば、ファイル生成コードは並列実行を正当化できるほど複雑ではありません。すべてのコンテキストの切り替えとチャネルを介したデータの移動は、並列処理の利点をすべて消費します。
generatefiles 関数のループに
time.sleep(time.millisecond * 10) のようなものを追加すると、より複雑なことを実行しているように見えます。期待どおりの結果が得られます - より多くのゴルーチンがより速く動作します。ただし、繰り返しになりますが、並列処理の追加作業が効果を発揮するのは、ある時点までです。
リーリー
ゴルーチンの数に直接依存します。すべてのゴルーチンはほぼ同時に終了するため、ループがワーカー スレッドと並行して実行されることはほとんどなく、実行にかかる時間が合計時間に加算されるだけです。次に、
files スライスに複数回追加すると、スライスが数倍に拡大し、データを新しい場所にコピーする必要があります。最初にすべての結果要素を埋めるスライスを作成することで、これを回避できます (幸いなことに、必要な要素の数が正確にわかっています)。
以上がgoroutine の数が増えると Go プログラムが遅くなるの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。