日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
創(chuàng)新互聯(lián)GO教程:Go語言多核并行化

Go語言具有支持高并發(fā)的特性,可以很方便地實(shí)現(xiàn)多線程運(yùn)算,充分利用多核心 cpu 的性能。

成都創(chuàng)新互聯(lián)專注于圖木舒克企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城網(wǎng)站開發(fā)。圖木舒克網(wǎng)站建設(shè)公司,為圖木舒克等地區(qū)提供建站服務(wù)。全流程按需搭建網(wǎng)站,專業(yè)設(shè)計(jì),全程項(xiàng)目跟蹤,成都創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

眾所周知服務(wù)器的處理器大都是單核頻率較低而核心數(shù)較多,對(duì)于支持高并發(fā)的程序語言,可以充分利用服務(wù)器的多核優(yōu)勢(shì),從而降低單核壓力,減少性能浪費(fèi)。

Go語言實(shí)現(xiàn)多核多線程并發(fā)運(yùn)行是非常方便的,下面舉個(gè)例子:

package main

import (
    "fmt"
)

func main() {
    for i := 0; i < 5; i++ {
        go AsyncFunc(i)
    }
}

func AsyncFunc(index int) {
    sum := 0
    for i := 0; i < 10000; i++ {
        sum += 1
    }
    fmt.Printf("線程%d, sum為:%d\n", index, sum)
}

運(yùn)行結(jié)果如下:

線程0, sum為:10000
線程2, sum為:10000
線程3, sum為:10000
線程1, sum為:10000
線程4, sum為:10000

在執(zhí)行一些昂貴的計(jì)算任務(wù)時(shí),我們希望能夠盡量利用現(xiàn)代服務(wù)器普遍具備的多核特性來盡量將任務(wù)并行化,從而達(dá)到降低總計(jì)算時(shí)間的目的。此時(shí)我們需要了解 CPU 核心的數(shù)量,并針對(duì)性地分解計(jì)算任務(wù)到多個(gè) goroutine 中去并行運(yùn)行。

下面我們來模擬一個(gè)完全可以并行的計(jì)算任務(wù):計(jì)算 N 個(gè)整型數(shù)的總和。我們可以將所有整型數(shù)分成 M 份,M 即 CPU 的個(gè)數(shù)。讓每個(gè) CPU 開始計(jì)算分給它的那份計(jì)算任務(wù),最后將每個(gè) CPU 的計(jì)算結(jié)果再做一次累加,這樣就可以得到所有 N 個(gè)整型數(shù)的總和:

type Vector []float64
// 分配給每個(gè)CPU的計(jì)算任務(wù)
func (v Vector) DoSome(i, n int, u Vector, c chan int) {
    for ; i < n; i++ {
        v[i] += u.Op(v[i])
    }
    c <- 1 // 發(fā)信號(hào)告訴任務(wù)管理者我已經(jīng)計(jì)算完成了
}
const NCPU = 16 // 假設(shè)總共有16核
func (v Vector) DoAll(u Vector) {
    c := make(chan int, NCPU) // 用于接收每個(gè)CPU的任務(wù)完成信號(hào)
    for i := 0; i < NCPU; i++ {
        go v.DoSome(i*len(v)/NCPU, (i+1)*len(v)/NCPU, u, c)
    }
    // 等待所有CPU的任務(wù)完成
    for i := 0; i < NCPU; i++ {
        <-c // 獲取到一個(gè)數(shù)據(jù),表示一個(gè)CPU計(jì)算完成了
    }
    // 到這里表示所有計(jì)算已經(jīng)結(jié)束
}

這兩個(gè)函數(shù)看起來設(shè)計(jì)非常合理,其中 DoAll() 會(huì)根據(jù) CPU 核心的數(shù)目對(duì)任務(wù)進(jìn)行分割,然后開辟多個(gè) goroutine 來并行執(zhí)行這些計(jì)算任務(wù)。

是否可以將總的計(jì)算時(shí)間降到接近原來的 1/N 呢?答案是不一定。如果掐秒表,會(huì)發(fā)現(xiàn)總的執(zhí)行時(shí)間沒有明顯縮短。再去觀察 CPU 運(yùn)行狀態(tài),你會(huì)發(fā)現(xiàn)盡管我們有 16 個(gè) CPU 核心,但在計(jì)算過程中其實(shí)只有一個(gè) CPU 核心處于繁忙狀態(tài),這是會(huì)讓很多Go語言初學(xué)者迷惑的問題。

官方給出的答案是,這是當(dāng)前版本的 Go 編譯器還不能很智能地去發(fā)現(xiàn)和利用多核的優(yōu)勢(shì)。雖然我們確實(shí)創(chuàng)建了多個(gè) goroutine,并且從運(yùn)行狀態(tài)看這些 goroutine 也都在并行運(yùn)行,但實(shí)際上所有這些 goroutine 都運(yùn)行在同一個(gè) CPU 核心上,在一個(gè) goroutine 得到時(shí)間片執(zhí)行的時(shí)候,其他 goroutine 都會(huì)處于等待狀態(tài)。從這一點(diǎn)可以看出,雖然 goroutine 簡(jiǎn)化了我們寫并行代碼的過程,但實(shí)際上整體運(yùn)行效率并不真正高于單線程程序。

雖然Go語言還不能很好的利用多核心的優(yōu)勢(shì),我們可以先通過設(shè)置環(huán)境變量 GOMAXPROCS 的值來控制使用多少個(gè) CPU 核心。具體操作方法是通過直接設(shè)置環(huán)境變量 GOMAXPROCS 的值,或者在代碼中啟動(dòng) goroutine 之前先調(diào)用以下這個(gè)語句以設(shè)置使用 16 個(gè) CPU 核心:

runtime.GOMAXPROCS(16)

到底應(yīng)該設(shè)置多少個(gè) CPU 核心呢,其實(shí) runtime 包中還提供了另外一個(gè) NumCPU() 函數(shù)來獲取核心數(shù),示例代碼如下:

package main

import (
"fmt"
"runtime"
)

func main() {
cpuNum := runtime.NumCPU() //獲得當(dāng)前設(shè)備的cpu核心數(shù)
fmt.Println("cpu核心數(shù):", cpuNum)

runtime.GOMAXPROCS(cpuNum) //設(shè)置需要用到的cpu數(shù)量
}

運(yùn)行結(jié)果如下:

cpu核心數(shù): 4


網(wǎng)站題目:創(chuàng)新互聯(lián)GO教程:Go語言多核并行化
本文路徑:http://www.dlmjj.cn/article/dhccpid.html