<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                ## GMP模型調度器 GMP模型調度器主要概念如下: * G(Goroutine): 即Go協程,每個go關鍵字都會創建一個協程 * M(Machine): 工作線程,在Go中稱為Machine * P(Processor): 處理器(Go中定義的一個摡念,不是指CPU),包含運行Go代碼的必要資源,也有調度goroutine的能力 ### 調度原理 ![](https://img.kancloud.cn/fa/83/fa837532e207117cb05de03c7fcb18e7_1024x768.png) * 全局隊列(Global Queue):存放等待運行的 G。 * P 的本地隊列:同全局隊列類似,存放的也是等待運行的 G,存的數量有限,不超過 256 個。新建 G’時,G’優先加入到 P 的本地隊列,如果隊列滿了,則會把本地隊列中一半的 G 移動到全局隊列。 * P 列表:所有的 P 都在程序啟動時創建,并保存在數組中,最多有 GOMAXPROCS(可配置) 個。 * M:線程想運行任務就得獲取 P,從 P 的本地隊列獲取 G,P 隊列為空時,M 也會嘗試從全局隊列拿一批 G 放到 P 的本地隊列,或從其他 P 的本地隊列偷一半放到自己 P 的本地隊列。M 運行 G,G 執行之后,M 會從 P 獲取下一個 G,不斷重復下去。 ![](https://img.kancloud.cn/30/11/3011e9a4be14e9ea5e143584cfaf9727_1240x698.png) 調度流程: 1. 我們通過 go func () 來創建一個 goroutine; 2. ?有兩個存儲 G 的隊列,一個是局部調度器 P 的本地隊列、一個是全局 G 隊列。新創建的 G 會先保存在 P 的本地隊列中,如果 P 的本地隊列已經滿了就會保存在全局的隊列中; 3. G 只能運行在 M 中,一個 M 必須持有一個 P,M 與 P 是 1:1 的關系。M 會從 P 的本地隊列彈出一個可執行狀態的 G 來執行;不考慮G進入系統調用或IO操作的情況下,P周期性的將G調度到M中執行,執行一小段時間,將上下文保存下來,然后將G放到隊列尾部,然后從隊列中重新取出一個G進行調度;如果 P 的本地隊列為空,先查詢全局隊列,如果全局隊列中也沒有G,則從其他MP組合偷取一部分可執行的P來執行(一般每次偷取一半); 4. 一個 M 調度 G 執行的過程是一個循環機制; 5. 當 M 執行某一個 G 時候如果發生了 syscall 或則其余阻塞操作,M 會阻塞,M將釋放P,進而某個空閑的M1(M1的來源有可能是M的緩存池,也可能是新建的)獲取P,繼續執行P隊列中剩下的G; 當M運行的某個G產生系統調用時,如下圖所示: ![](https://img.kancloud.cn/09/b7/09b7780100c33083307f5158f9e79268_550x400.png) 6. 當G0系統調用結束后,根據M0是否能獲取到P,將會將G0做不同的處理: a> 如果有空閑的P,則獲取一個P,繼續執行G0; b> 如果沒有空閑的P,則將G0放入全局隊列,等待被其他的P調度。然后M0將進入緩存池睡眠 --- *說明:每個P會周期性地查看全局隊列中是否有G待運行并將其調度到M中執行,全局隊列中G的來源,主要有從系統調用中恢復的G。之所以P會周期性地查看全局隊列,也是為了防止全局隊列中的G被餓死* ### 調度器的設計策略 復用線程:避免頻繁的創建、銷毀線程,而是對線程的復用。 1)work stealing 機制 ? 當本線程無可運行的 G 時,嘗試從其他線程綁定的 P 偷取 G,而不是銷毀線程。 2)hand off 機制 ? 當本線程因為 G 進行系統調用阻塞時,線程釋放綁定的 P,把 P 轉移給其他空閑的線程執行。 利用并行:GOMAXPROCS 設置 P 的數量,最多有 GOMAXPROCS 個線程分布在多個 CPU 上同時運行。GOMAXPROCS 也限制了并發的程度,比如 GOMAXPROCS = 核數/2,則最多利用了一半的 CPU 核進行并行。 搶占:在 coroutine 中要等待一個協程主動讓出 CPU 才執行下一個協程,在 Go 中,一個 goroutine 最多占用 CPU 10ms,防止其他 goroutine 被餓死,這就是 goroutine 不同于 coroutine 的一個地方。 全局 G 隊列:在新的調度器中依然有全局 G 隊列,但功能已經被弱化了,當 M 執行 work stealing 從其他 P 偷不到 G 時,它可以從全局 G 隊列獲取 G ### Goroutine vs Machine * P的數量由啟動時環境變量 $GOMAXPROCS 或者是由 runtime 的方法 GOMAXPROCS() 決定。這意味著在程序執行的任意時刻都只有 $GOMAXPROCS 個 goroutine 在同時運行 * M的數量由go語言本身的限制,go程序啟動時,會設置M的最大數量,默認10000. 但是內核很難支持這么多的線程數,所以這個限制可以忽略;runtime/debug中的SetMaxThreads 函數,設置M的最大數量;一般大于等于P的個數 > P vs M 的創建 P何時創建:在確定了P的最大數量n后,運行時系統會根據這個數量創建n個P。 M 何時創建:當沒有足夠的 M 來關聯 P 并運行其中的可運行的 G。比如所有的 M 此時都阻塞住了,而 P 中還有很多就緒任務,就會去尋找空閑的 M,而沒有空閑的,就會去創建新的 M GOMAXPROCS設置對性能的影響 一般來講,程序運行時就將GOMAXPROCS大小設置為CPU核數,可讓Go程序充分利用CPU;在某些IO密集型的應用里,這個值可能并不意味著性能最好。 理論上當某個Goroutine進入系統調用時,會有一個新的M被啟用或創建,繼續占滿CPU。 但由于Go調度器檢測到M被阻塞是有一定延遲的,也即舊的M被阻塞和新的M得到運行之間是有一定間隔的,所以在IO密集型應用中不妨把GOMAXPROCS設置的大一些,或許會有好的效果
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看