⚠️ 注意:有限維護
本專案已不再積極維護。雖然現有版本仍然可用,但沒有計劃的更新、錯誤修復、新功能或安全補丁。使用者應注意,漏洞可能不會得到解決。
使用 NVIDIA MPS 執行 TorchServe¶
為了部署機器學習模型,TorchServe 會在獨立的程序中啟動每個 worker,從而將每個 worker 彼此隔離。每個程序建立自己的 CUDA 上下文來執行其 kernel 並訪問分配的記憶體。
雖然 NVIDIA GPU 在預設設定下允許在單個裝置上執行多個程序的 CUDA kernel,但這存在以下缺點:
kernel 的執行通常是序列化的
每個程序都建立自己的 CUDA 上下文,這會佔用額外的 GPU 記憶體
針對這些場景,NVIDIA 提供了多程序服務(MPS),它可以:
允許多個程序在同一個 GPU 上共享同一個 CUDA 上下文
並行執行它們的 kernel
這可以帶來以下結果:
在同一個 GPU 上使用多個 worker 時提高效能
由於共享上下文而降低 GPU 記憶體利用率
為了利用 NVIDIA MPS 的優勢,我們需要在啟動 TorchServe 本身之前使用以下命令啟動 MPS 守護程序。
sudo nvidia-smi -c 3
nvidia-cuda-mps-control -d
第一個命令為 GPU 啟用獨佔處理模式,僅允許一個程序(MPS 守護程序)使用它。第二個命令啟動 MPS 守護程序本身。要關閉守護程序,我們可以執行
echo quit | nvidia-cuda-mps-control
有關 MPS 的更多詳細資訊,請參閱 NVIDIA 的 MPS 文件。需要注意的是,由於硬體資源有限,MPS 只允許 48 個程序(對於 Volta GPU)連線到守護程序。向同一個 GPU 新增更多客戶端/worker 將導致失敗。
基準測試¶
為了展示 TorchServe 在啟用 MPS 後的效能,並幫助決定是否為您的部署啟用 MPS,我們將使用代表性工作負載進行一些基準測試。
首先,我們希望研究在啟用 MPS 的情況下,worker 的吞吐量如何隨不同的操作點變化。作為我們基準測試的示例工作負載,我們選擇了 HuggingFace Transformers 序列分類示例。我們在 AWS 的 g4dn.4xlarge 例項和 p3.2xlarge 例項上執行基準測試。這兩種例項型別每個例項提供一個 GPU,這將導致多個 worker 排程在同一個 GPU 上。對於基準測試,我們重點關注由 benchmark-ab.py 工具測量的模型吞吐量。
首先,我們測量單個 worker 在不同批次大小下的吞吐量,這將顯示 GPU 計算資源在何時被完全佔用。其次,對於我們預計 GPU 仍有一些剩餘資源可共享的批次大小,我們測量部署兩個 worker 時的吞吐量。對於每個基準測試,我們執行五次執行並取執行結果的中位數。
我們對基準測試使用以下 config.json 檔案,只相應地覆蓋 worker 數量和批次大小。
{
"url":"/home/ubuntu/serve/examples/Huggingface_Transformers/model_store/BERTSeqClassification",
"requests": 10000,
"concurrency": 600,
"input": "/home/ubuntu/serve/examples/Huggingface_Transformers/Seq_classification_artifacts/sample_text_captum_input.txt",
"workers": "1"
}
請注意,我們將併發級別設定為 600,這將確保 TorchServe 內部的批次聚合將批次填充到最大批次大小。但與此同時,這將扭曲延遲測量結果,因為許多請求將在佇列中等待處理。因此,在下文中我們將忽略延遲測量。
G4 例項¶
我們首先對 G4 例項執行單 worker 基準測試。在下圖中,我們看到,批次大小達到四時,吞吐量隨批次大小穩步增加。

接下來,我們將 worker 數量增加到兩個,以比較啟用 MPS 和未啟用 MPS 時的吞吐量。為了為第二組執行啟用 MPS,我們首先為 GPU 設定獨佔處理模式,然後按照上面所示啟動 MPS 守護程序。
我們根據之前的發現選擇批次大小在一到八之間。在圖中我們可以看到,對於批次大小為 1 和 8 的情況,吞吐量效能可能更好(最高提高 18%),而對於其他批次大小可能更差(降低 11%)。對此結果的一種解釋可能是,當我們在一個 worker 中執行 BERT 模型時,G4 例項沒有太多資源可共享。

P3 例項¶
接下來,我們將使用更大的 p3.2xlarge 例項執行相同的實驗。使用單個 worker,我們獲得以下吞吐量值

我們可以看到吞吐量穩步增加,但當批次大小超過八時,回報遞減。最後,我們在 P3 例項上部署兩個 worker,並比較啟用和未啟用 MPS 時它們的執行情況。我們可以看到,對於批次大小在 1 到 32 之間的情況,啟用 MPS 時的吞吐量始終更高(最高提高 25%),批次大小為 16 時除外。

總結¶
在上一節中,我們看到透過為執行相同模型的兩個 worker 啟用 MPS,我們得到了混合結果。對於較小的 G4 例項,我們只在某些操作點看到了好處,而對於較大的 P3 例項,我們看到了更一致的改進。這表明使用 MPS 執行部署的吞吐量優勢高度依賴於工作負載和環境,需要針對特定情況使用適當的基準測試和工具來確定。需要注意的是,之前的基準測試僅側重於吞吐量,忽略了延遲和記憶體佔用。由於使用 MPS 只會建立一個 CUDA 上下文,因此可以將更多 worker 打包到同一個 GPU 上,這在相應場景中也需要考慮。