GPT-6 訓練期間的 GPU 利用率與閒置資源處理

你的現代化 GPU 叢集在理論上擁有驚人的峰值效能。但對許多團隊來說,現實卻截然不同。你常常會看到平均 GPU 利用率驟降到 30% 以下。承諾與現實之間的這道鴻溝,會讓你付出高昂代價。怎樣才能把 GPU 利用率推近 90%?那些依然閒置的 GPU 又該如何處理?在這種面向大型語言模型工作的 AI 訓練環境中,你必須採取嚴謹的方法。規模、成本與算力浪費帶來的維運痛點,要求你立刻行動。每一張閒置的 GPU,都是對預算與進度的直接打擊。在如此規模下管理一個 LLM,幾乎容不得任何低效。你需要一套清晰的訓練最佳化策略。
為大型語言模型訓練定義 GPU 利用率指標
為什麼原始利用率百分比會誤導你
你打開 nvidia-smi,看到 GPU 利用率是 100%。你以為硬體運作得無比完美。這個判斷其實並不成立。你看到的這個百分比,衡量的只是一個非常狹窄的面向。它只追蹤在取樣視窗期間,是否有任何核心在執行。它並不能衡量你的模型是否高效利用了硬體。
根據 NVML 的定義,「utilization(利用率)」表示在過去一個取樣週期內,某些活動發生的時間百分比。GPU utilization 表示一個或多個核心執行時所占的時間百分比。Memory utilization 表示全域記憶體被讀取或寫入時所占的時間百分比。
考慮一個簡單的核心:它只在一個 Streaming Multiprocessor 上執行無限迴圈。你的 GPU 可能擁有數十個 SM。真正的計算使用率,其實等於 1 除以 SM 總數。然而,nvidia-smi 仍可能顯示 100% 利用率。這樣的差異會製造一種虛假的信心。你以為自己昂貴的叢集已經在最佳狀態下運作。實際上,你的模型可能只是輕微觸及了硬體能力。原始利用率數字掩蓋了真相,也掩蓋了你的 AI 訓練效率問題。
關鍵指標:MFU、HFU 與記憶體頻寬
你需要更好的測量方式。模型 FLOPs 利用率(Model FLOPs Utilization,MFU)能提供更清晰的視角。MFU 將模型實際執行的浮點運算,與硬體理論峰值進行對比。這個指標能揭示你究竟利用了多少 GPU 的數學計算能力。
硬體 FLOPs 利用率(Hardware FLOPs Utilization,HFU)則提供了另一個角度。它會把硬體執行的所有操作都計算進去,包括那些低效的操作。很多時候,真正的限制並不是計算,而是記憶體頻寬。你的模型可能不是在等算力,而是在等資料搬移。GPU 之間的通訊開銷同樣會造成停頓。這些瓶頸,比單純的 SM 活躍度更重要。你必須把這些指標結合起來一起追蹤。它們會揭示你的 LLM 訓練究竟把效能浪費在了哪裡。只有這樣,你才能真正找到最佳化機會。
識別大型語言模型訓練中的瓶頸
計算、記憶體與通訊開銷
一次大型語言模型訓練,通常會遭遇三類主要瓶頸。計算受限的層會把算術單元推到極限。記憶體受限的權重更新會因等待資料搬移而停滯。通訊受限的梯度同步,則會讓整個叢集在 GPU 交換梯度時暫停。每一種瓶頸,都會偷走原本可用於有效工作的時間。
通訊開銷往往破壞力最大。一個擁有 1,000 張 GPU 的叢集,理論能力極其驚人。但在實務中,硬體花在「交談」上的時間,往往比「思考」還多。
一個擁有 1,000 張 GPU 的叢集具備驚人的理論能力,但在實際中,硬體往往把更多時間花在「交談」而不是「思考」上。在分散式訓練中,梯度同步就是瓶頸。如果某個節點的反向傳播晚了 10 分鐘才完成,那麼整個叢集都必須等待,這會導致長時間的閒置計算時間。
梯度同步中的 all-reduce 就會帶來這種延遲。在樸素的資料平行訓練裡,每個參數張量都需要各自進行一次 all-reduce。成千上萬次小型操作,每一次都要承擔啟動延遲。整個叢集就在等待通訊完成。你可以透過更好的演算法來降低這部分開銷:
| 演算法 | 延遲步數 | 對 GPU 閒置時間的影響 |
|---|---|---|
| Ring All-Reduce | 2(N-1) 個順序步驟 | 在大規模場景下延遲較高;閒置時間會隨 GPU 數量線性增加。 |
| Tree All-Reduce | 2*log2(N) 個步驟 | 延遲更低;與 ring all-reduce 相比,可在大型叢集中顯著減少閒置時間。 |
Tree All-Reduce 將延遲步數從線性降低到對數級。如此一來,叢集等待的時間就更少。記憶體受限的操作同樣會偷走效能。權重更新和最佳化器步驟都需要讀寫參數。一次最佳化器更新,需要從記憶體中讀取完整的模型狀態。此時記憶體頻寬就會成為限制因素。像大型矩陣乘法這樣的計算受限層,確實能讓一張 GPU 保持忙碌,但即便如此,仍然存在最佳化空間。
儲存與資料載入:隱藏的罪魁禍首
你可能已經最佳化了每一個計算與通訊步驟,可 GPU 還是處於閒置狀態。真正的原因,往往隱藏在儲存 I/O 裡。很多資料科學家會看到 GPU 利用率低到 30%,原因就是在等待資料載入。計算流程會停住,因為硬體完成工作的速度,比儲存系統提供新資料的速度還快。
LLM 訓練流程依賴高速的資料供給。如果儲存系統跟不上,叢集裡的每一張加速器都只能等待。規模越大,這個問題越嚴重。你必須精心設計資料載入流程。使用非同步預取。快取高頻存取資料。把訓練資料放在高速本機 NVMe 磁碟上。每一步,都是在減少硬體等待資料的時間。最佳化 AI 訓練流程,意味著要關注整條鏈路上的每一個環節。
透過平行化最大化 GPU 利用率
平衡資料平行、張量平行與管線平行
你無法只用單一裝置訓練一個大型語言模型。模型本身就會超過任何單張 GPU 的記憶體容量。你必須把工作拆分到多張 GPU 上。主要有三種拆分策略。每一種在通訊開銷與計算效率上都有不同權衡。選對組合,會直接影響整體效能。
資料平行會在每個加速器上複製完整模型。每個裝置處理不同批次的資料。每個訓練步驟之後,裝置之間透過 all-reduce 交換梯度。這種方式的通訊頻率較低。但它要求單一模型能夠裝進單一裝置。對於超大型模型來說,光模型本身就已經超限了。
張量平行則把單層的權重切分到多張 GPU 上。每個裝置持有每個張量的一部分。裝置之間必須在每一層內部反覆交換中間結果,並透過 all-reduce 完成同步。這會帶來很高的通訊開銷。這種技術要求使用像 NVLink 這樣的高頻寬互連。更高的張量平行度會降低每個裝置的記憶體占用,但也會縮小矩陣規模,導致那些為大型矩陣最佳化的核心無法被充分利用。
管線平行會把模型分成若干階段。每個階段由一組連續層組成。某個裝置群組負責一個階段。活化值在階段之間傳遞。這種方式的通訊頻率較低,但會遭遇 pipeline bubble(管線氣泡)——也就是階段間的閒置時間。某個較慢或記憶體負載較高的階段,會拖慢後續所有階段。
對於超大型模型,你必須把這三種策略結合起來。這種方法被稱為 3D 平行,也就是把資料平行、張量平行和管線平行疊加使用。它的通訊成本最高。你需要具備拓樸感知能力的排程方式,才能避免瓶頸。多數生產系統會採用混合配置,例如張量平行度為 2、管線平行度為 2。這樣的平衡可以在拆分模型的同時,把通訊控制在可接受範圍內。某些模型規模下,經過改造的 ZeRO stage-3 變體,在通訊開銷上甚至可能優於張量平行。
透過微批次處理減少管線氣泡
在管線平行中,pipeline bubble 是最主要的閒置時間來源。氣泡大小取決於階段數與微批次數。其低效程度大致與 \(Nstages – 1\) 除以 \(Nmicrobatches\) 成正比。若有 8 個階段、16 個微批次,理論氣泡可達到約 44%。
微批次處理能夠降低這種氣泡。與其處理一個大批次,不如把它拆成許多更小的微批次。你把這些微批次一個接一個地送入管線。這樣便能在所有階段中形成穩定的工作流。預熱階段依舊存在一些閒置時間,但在穩態下,各階段都能持續保持忙碌。
1F1B 排程比早期方法更高效。它包括一個預熱階段、一個穩態階段——每個 worker 執行一次前向傳播和一次反向傳播——以及一個收尾階段,用於完成剩餘反向傳播。與 GPipe 方法相比,它降低了記憶體使用。
更先進的排程策略,例如 Zero Bubble,可以透過把前向與反向計算進一步拆分成更小單元,來繼續減少閒置時間。這些策略會交錯安排反向傳播中的不同計算部分,從而在保持同步訓練優勢的同時,將氣泡壓縮到接近於零。對於最大化 AI 訓練吞吐而言,這一點至關重要。
但微批次處理也有代價。要減少氣泡,就需要足夠多的微批次。這往往會迫使你採用非常大的全域 batch size。過大的 batch size 可能損害收斂效果。當你把管線平行與資料平行結合時,還必須考慮單裝置 batch size 被進一步攤薄的問題。你必須在高吞吐與高模型品質之間取得平衡。對於 8 個管線階段,理論效率可達 87.5%。但現實系統通常只能達到 60% 到 75%,原因在於微批次處理額外開銷與負載不均衡。這是大規模 LLM 訓練中的常見挑戰。
最佳化訓練迴圈以提升 GPU 利用率
利用混合精度與梯度累積
你可以透過從 FP32 切換到 BF16 來提升吞吐。下表展示了兩者的關鍵差異:
| 指標 | FP32 | BF16(混合精度) |
|---|---|---|
| A100 Tensor Core 吞吐 | 較低 | 約 312 TFLOPS |
| 每個數值的記憶體占用 | 32 位元 | 16 位元(減少 50%) |
| 動態範圍 | 與 FP32 相同 | 與 FP32 相同 |
| 是否需要 loss scaling | 不需要 | 不需要 |
BF16 為指數分配 8 位元、為尾數分配 7 位元。因此它擁有與 FP32 相同大小的指數位。它的動態範圍與 FP32 一致。這樣你就能避免下溢與上溢問題,也不需要 loss scaling。每個數值減少 50% 的記憶體占用,意味著你可以使用更大的 batch size。更小的資料體積也會減少傳輸量,從而帶來效能提升。
梯度累積能讓你在不增加額外記憶體成本的前提下,模擬更大的 batch size。標準批次處理會增加記憶體使用,因為你必須保存中間活化值。梯度累積改變了這個過程。你用更小的 micro-batch 處理資料。你在這些 micro-batch 之間累加梯度。只有在累積到足夠多的梯度之後,才更新參數。有效 batch size 等於 micro-batch size 乘以 gradient steps 再乘以 device count。這個技巧與資料平行配合良好,因為每個裝置都可以獨立累積梯度。你也可以把它與跨多節點的資料平行結合起來使用。透過平滑計算峰值,你可以讓 GPU 利用率維持在較高水準。
精簡資料載入與前處理
你的加速器完成計算的速度,可能快於儲存系統提供資料的速度。這種不匹配會導致閒置時間。你必須精簡資料流程。
使用非同步預取與快速本機儲存,把資料載入與計算重疊起來執行。這樣可以消除停頓,讓你的硬體在 LLM 訓練期間始終保持高效運轉。
使用分析工具診斷閒置 GPU
透過監控識別閒置狀態
你需要看清每一秒鐘加速器究竟在做什麼。使用可用的 GPU 監控工具來追蹤 SM 活躍度與記憶體頻寬利用率。較低的 SM 活躍度說明 GPU 正在等待,而不是在計算。
監控「至少有一個 warp 處於活躍狀態的時間占比」。如果這個值低於 0.5,就表示利用效果不佳。若數值非常低,則表示 SM 在大部分時間裡都處於閒置狀態。記憶體頻寬利用率則揭示了記憶體介面是否在積極傳輸資料。如果這裡的數值也很低,就表示你的硬體是在等待,而不是在工作。
常見的閒置模式及其根因
你會遇到幾種反覆出現的閒置模式。同步屏障會造成最明顯的停頓。當某個節點完成反向傳播的時間較晚時,其他所有加速器都必須等待。這種模式會表現為所有裝置同時出現週期性的活躍度下跌。
Pipeline bubble 是另一個持續存在的元兇。管線平行天生就會引入這種閒置模式。微批次按順序穿過各個階段。管線必須排空,然後新任務才能繼續進入。在這個轉換過程中,有些 GPU 會暫時空置。即使使用了最佳化排程,仍然可能產生顯著的閒置時間。
I/O 瓶頸會導致長時間的閒置。有研究表明,訓練時間中多達 70% 可能花在等待資料上,導致 GPU 處於閒置狀態。識別這些「指紋」有助於你精準鎖定最佳化方向。你的 LLM 訓練效能,取決於你是否能判斷哪一種模式主導了目前工作負載。只有這樣,你才能對症下藥。
透過動態排程處理閒置 GPU
你無法僅靠最佳化就消除所有閒置週期。同步屏障、管線氣泡與資料載入等待,總會留下空檔。問題在於,你要如何利用這些空檔。動態排程提供了一種解法。你需要把叢集視為一個活的系統。作業會根據即時可用資源進行伸縮。
實現彈性訓練與搶占
彈性訓練會改變作業邊界。你不再定義一個固定的 worker 數量,而是定義最小值與最大值範圍。TorchElastic 是 PyTorch 的工作負載管理工具,它讓這種方式變得切實可行。你可以在作業定義中設定 minReplicas 與 maxReplicas。系統會在這個範圍內上下擴縮 worker,而不必中斷訓練。
這種架構會把控制平面元件與 worker 節點分離。你把 TorchElastic controller 和 Rendezvous server 執行在不可搶占的 CPU 節點上。這些核心元件必須保持可用。worker 則執行在 GPU spot instance 上。成本節省就來自這種部署方式。當某個 spot 節點被驅逐時,TorchElastic 不會讓整個作業失敗。只有當活躍 worker 數量跌破 minReplicas 時,controller 才會判定作業失敗。否則,它會重新排程遺失的 pods,並從最近一次 checkpoint 恢復訓練。
這種設計能優雅地處理搶占。失去一個 worker 變得可以接受。你的訓練資料與作業狀態存放在掛載的雲端儲存上。系統可以無縫恢復。如此一來,原本可能閒置的 GPU 時間,就被轉化成了可產生價值的訓練週期。
縮容與暫停之間的取捨非常關鍵。縮容會釋放 GPU 給其他作業使用。暫停則會保留資源分配,但讓它們處於閒置狀態。對於存在競爭性工作負載的叢集來說,縮容更高效。你可以把硬體釋放給更高優先級任務。暫停只適合很短暫的空檔。但如果暫停時間較長,就會浪費容量。具體選擇取決於你的工作負載結構。對於 LLM 訓練而言,在可預測的閒置期進行縮容,通常是更優方案。你既能把硬體回收給其他任務使用,又保留了在需要時再次擴容的能力。
Kubernetes 中的動態資源分配
Kubernetes 把這種動態行為擴展到了整個叢集。NVIDIA GPU Operator 負責部署所需元件。GPU Device Plugin 以 DaemonSet 形式執行在每個 GPU 節點上。在初始化期間,外掛程式會呼叫 NVIDIA Management Library(NVML)查詢可用 GPU。它會取得顯示記憶體容量、計算能力以及互連拓樸等資訊。隨後,外掛程式透過 nvidia.com/gpu 這個資源名稱,將這些 GPU 註冊給 kubelet。Pods 便可透過標準資源宣告來申請 GPU。
你必須決定,如何在多個工作負載之間共享 GPU。主要有三種方案。下表總結了它們之間的權衡:
| 方案 | 隔離性 | 靈活性 | 最適用場景 |
|---|---|---|---|
| MIG | 強(硬體級) | 靜態(預定義設定檔) | 推論、多租戶 |
| Time Slicing | 弱(無顯示記憶體隔離) | 動態(無需預先分區) | Notebook、批次作業 |
| Custom Scheduler | 軟隔離(基於排程策略) | 高度可配置 | 受信任的內部使用者 |
Time slicing 可執行於任何 NVIDIA GPU 上。它是最容易起步的方案。但它不提供顯示記憶體隔離,也不提供故障隔離。MIG 提供硬體級隔離和可預測效能,但依賴靜態設定檔。重新設定 MIG profile 在維運上較為複雜,甚至可能需要重設 GPU。Custom scheduler 擁有很高的靈活性,但代價是更高的維運複雜度。你需要根據自身工作負載需求來做選擇。
具備 GPU 感知能力的排程機制,可以讓閒置資源轉化為有效工作。你可以把一個節點配置為讓多個 pods 共享其 GPU 時間。某個 pod 在管線氣泡期間執行,就等於利用了本來會白白流失的算力週期。NVIDIA GPU Operator 負責管理所有 GPU 相關資源的部署與生命週期。它會部署驅動程式、裝置外掛程式和監控工具。GPU Feature Discovery 元件會掃描節點上的 GPU 能力,並將顯示記憶體大小與 CUDA capability 等資訊暴露出來,供工作負載使用。MIG Manager 則允許把硬體切分為更小的實例。每個分區都可以分配給不同工作負載。這樣一來,一張實體 GPU 就能被多個工作負載共享,從而最大化 GPU 利用率。
LLM 訓練作業保留其已分配的容量。輔助任務則去填補空隙。每一個閒置週期,都會變成一次產出價值的機會。
將閒置 GPU 重新用於輔助工作負載
在管線氣泡期間進行推測式推論
Pipeline bubble 會在訓練計畫中製造出可預測的空檔。這些 GPU 閒置視窗會規律性地反覆出現。你可以用它們來做有價值的工作。推測式推論就是一個很有吸引力的選擇。這種技術會讓草稿模型先於主驗證模型執行。草稿模型提前生成 token 序列。隨後,你的主模型並行驗證多個 token。這樣就能在不犧牲準確性的前提下,加速推論過程。
SpecInF 就是這一思路的一個實際實作。該系統會在計算氣泡期間排程推測式推論任務。訓練作業始終保有最高優先級。推論工作只在空檔中填充執行。如此一來,浪費掉的週期就轉化成了有價值的輸出。你獲得了額外的推論吞吐,卻不必延長訓練時間線。關鍵在於排程精度。你必須讓推論任務與每一個氣泡的精確持續時長相匹配。較短的氣泡適合小型草稿模型。較長的空檔,則可以容納更重一些的驗證工作。
在資源隔離下執行輔助任務
除了推論之外,你還可以在閒置時段執行其他工作負載。資料前處理通常會消耗大量 CPU 時間。你可以在訓練暫停期間,把這類工作卸載到 GPU 上。針對驗證集的評估任務也很適合。它們需要的是突發式算力,而不是持續占用。對更小模型進行面向下游任務的微調,也是一個可行選項。每一種輔助作業,都能為你的 LLM 生態增加價值。
在共享硬體時,資源隔離至關重要。你絕不能讓輔助任務拖慢主要訓練作業。硬體分區方案,例如 NVIDIA Multi-Instance GPU(MIG),可以把一張實體 GPU 劃分成多個相互隔離的實例。每個分區都擁有專屬的顯示記憶體與計算切片。這種硬體級隔離可以防止彼此干擾。Time slicing 則提供了更靈活的替代方案。多個工作負載透過快速內容切換來共享同一張 GPU。這種方式可執行於任何 NVIDIA 硬體上。然而,它的隔離能力弱於 MIG。
你的選擇取決於工作負載特徵。MIG 適合對效能有嚴格要求的生產環境。Time slicing 更適合探索性任務和開發工作。你還必須考慮安全邊界。不受信任的工作負載需要 MIG 提供的更強隔離。受信任的內部任務則可以安全地使用 Time slicing。這種資源分配策略,能確保每一張 GPU 都在創造價值。你的訓練效能得到保護,而閒置容量則被用於其他用途。最終結果,是一個持續朝多個目標同時運轉的叢集。
從原始利用率指標,到動態排程系統,你已經走過了一條完整路徑。這段過程揭示了一個根本事實:實現高 GPU 效能,並不是一個終點,而是一個持續進行分析、調校與適配的循環。每一次訓練執行,都會暴露新的瓶頸。每修復一個問題,往往又會顯露出更深一層的限制。
大規模 LLM 工作的未來,在於可組合、可彈性的基礎設施。閒置 GPU 應該被視為一種設計缺陷,而不是不可避免的現實。你必須把每一張未被使用的加速器都看作一種機會。建立「資源 stewardship(資源治理)」的思維方式。用輔助任務填補空檔。條件允許時就縮容。把空餘容量重新投入評估任務或更小模型。你的訓練會從這種紀律性關注中受益。你的預算也會因此受益。你的 GPU 的每一個週期,都應該產生價值。把這一點,變成你的標準實務。
常見問題
原始 GPU 利用率和 MFU 有什麼區別?
原始利用率只追蹤在一個取樣週期內是否有任何核心執行。即使你的硬體幾乎沒有真正發力,它也可能顯示 100%。MFU 衡量的是實際算術效率相對於理論峰值的比例。這個指標更能揭示你的 LLM 訓練真實效能。
我該如何找出訓練中的主要瓶頸?
使用監控工具追蹤 SM 活躍度與記憶體頻寬。同步屏障通常表現為所有 GPU 同時出現活躍度下跌。管線氣泡則表現為規律性的空檔。若資料載入跟不上,儲存 I/O 就會造成停頓。
我能在不拖慢主要任務的情況下使用閒置 GPU 嗎?
可以。你可以使用硬體分區或 Time slicing 實現資源隔離。在管線氣泡期間排程推測式推論。也可以在空檔中執行資料前處理或評估任務。動態排程工具能夠高效管理這些資源。
大規模分散式訓練中的管線氣泡是怎麼產生的?
管線氣泡發生在不同階段完成時間不一致時。某個較慢的階段會拖住後續所有 GPU。微批次處理可以減少閒置時間。更先進的排程技術還能進一步壓縮這些空檔。
