ホームページ  >  記事  >  バックエンド開発  >  Golang は並列処理を実装します

Golang は並列処理を実装します

WBOY
WBOYオリジナル
2023-05-21 19:12:36600ブラウズ

ビッグデータ、人工知能、その他のテクノロジーの急速な発展に伴い、高性能と高い同時実行性に対する要求もますます高まっています。この文脈において、golang は高い同時実行性と高性能のプログラミング言語として非常に人気があります。その中でも、golang の並列機能は他の言語と区別する重要な機能の 1 つです。この記事では主に、golang で並列処理を実装する方法と、並列処理によってもたらされるパフォーマンスの向上について説明します。

1. 並列処理の概要

並列とは、複数のタスクを同時に実行することを指しますが、複数のタスクを同時に実行するという意味ではありません。単一のCPUでは一度に1命令しか実行できませんが、各命令の実行時間は非常に短く、CPUは高速回転することでユーザー視点のマルチタスクを完了します。この高速回転によりタスクの切り替え時間が非常に短くなり、あたかも複数のタスクが同時に実行されているかのように見える、これが並列処理です。

実際のアプリケーションでは、通常、並列テクノロジを使用して高同時実行性と高密度のビジネス シナリオを処理します。実行効率です。 Golang では、ゴルーチンは軽量スレッドと呼ばれ、スレッドよりも軽量で効率的であり、ゴルーチンの起動に必要なオーバーヘッドはほとんどありません。したがって、golang は並列処理の実装に当然適しています。

2. Goroutine の並列処理

golang では、Goroutine を通じて並列操作を実装できます。 goroutine は golang ランタイムシステムによって管理される軽量なスレッドであり、オペレーティングシステムのスレッドのように大量のメモリを消費しないため、多数の goroutine を同時に起動してタスクの待ち時間を短縮し、プログラムの実行を向上させることができます。効率。 goroutine の起動方法を見てみましょう。

1. goroutine の定義

golang で goroutine を定義する方法は非常に簡単で、単独で実行する必要がある関数本体の前にキーワード go を追加するだけです。例:

go func() {
    fmt.Println("Hello, goroutine!")
}()

2. goroutine の開始

goroutine の開始は非常に簡単で、関数を呼び出すだけです。例:

func main() {
    go func() {
        fmt.Println("Hello, goroutine!")
    }()
    fmt.Println("Hello, main!")
    time.Sleep(time.Second)
}

上記のコードでは、文を出力するゴルーチンを開始しますが、メイン関数は独自の単語を出力し続け、1 秒間停止します。この時点でプログラムを実行すると、main 関数と goroutine が交互に Hello, main! と Hello, goroutine! を出力することがわかり、2 つの関数が異なる goroutine で並列実行されていることがわかります。

3. Channel

Channel は golang が提供するスレッド間通信機構で、ゴルーチン間でデータを転送する機能があります。チャネルには、送信側と受信側の 2 つのエンドポイントがあります。キーワード make を使用してチャネルを作成し、<- を使用してデータを転送できます。例:

func goroutineFunc(c chan int) {
    c <- 1
}

func main() {
    c := make(chan int)
    go goroutineFunc(c)
    result := <-c
    fmt.Println(result)
}

上記のコードでは、ゴルーチンの開始時にチャネル c も作成し、ゴルーチンで c <- 1 を使用してチャネルに 1 を書き込みます。最後に、result := <-c を通じてデータを読み取ります。この方法では、異なるゴルーチン間でデータを交換し、大規模な並列処理を実現できます。

3. 並列コンピューティング

並列コンピューティングを実行したい場合は、実行のためにコンピューティング タスクを異なるゴルーチンに割り当て、チャネルを通じてデータを交換する必要があります。以下では、サンプル コードを使用して、golang を使用して並列コンピューティングを実装する方法を示します。

1. pi 値の並列計算

func pi(n int) float64 {
    ch := make(chan float64)
    for i := 0; i < n; i++ {
        go func(start, end int) {
            sum := 0.0
            for j := start; j < end; j++ {
                x := (float64(j) + 0.5) / float64(n)
                sum += 4.0 / (1.0 + x*x)
            }
            ch <- sum
        }(i*n/n, (i+1)*n/n)
    }
    result := 0.0
    for i := 0; i < n; i++ {
        result += <-ch
    }
    return result / float64(n)
}

func main() {
    fmt.Println(pi(10000))
}

上記のコードでは、まず長さ n のチャネル ch を作成し、n 個のゴルーチンを使用して計算し、計算結果を書き込みます。チャンネルの真ん中。最後に、チャネルからすべての結果の合計を読み取り、π 値を計算します。並列コンピューティングにより、計算速度を大幅に向上させることができます。

2. 行列乗算の並列計算

func MatrixMul(a, b [][]int) [][]int {
    m, n, p := len(a), len(a[0]), len(b[0])
    c := make([][]int, m)
    for i := 0; i < m; i++ {
        c[i] = make([]int, p)
    }

    ch := make(chan int)
    for i := 0; i < m; i++ {
        for j := 0; j < p; j++ {
            go func(x, y int) {
                sum := 0
                for k := 0; k < n; k++ {
                    sum += a[x][k] * b[k][y]
                }
                ch <- sum
            }(i, j)
        }
    }

    for i := 0; i < m; i++ {
        for j := 0; j < p; j++ {
            c[i][j] = <-ch
        }
    }

    return c
}

func main() {
    a := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
    b := [][]int{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}
    fmt.Println(MatrixMul(a, b))
}

上記のコードでは、ゴルーチンを使用して行列の積を並列計算しています。コンピューティングタスクをゴルーチンに割り当て、チャネルを通じてデータを交換します。最後に、チャネルからすべての結果を読み取り、製品マトリックスを形成します。並列コンピューティングにより、コンピューティング速度が向上し、コンピューティング コストが削減されます。

概要

この記事では主にgoroutineを使ってgolangで並列計算を実装する方法と、goroutineとチャネルの使い方を紹介します。並列コンピューティングにより、コンピューティング タスクを複数のゴルーチンに割り当てることができるため、プログラムの実行効率が向上し、高同時実行性と高密度のビジネス シナリオの処理に適しています。 Golang に組み込まれている goroutine とチャネルのメカニズムにより、他の言語よりも並列操作が簡単かつ効率的になります。

以上がGolang は並列処理を実装しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
前の記事:golangノード転送次の記事:golangノード転送