故障排除¶
本文件概述了一些您可以考慮的故障排除策略。如果您認為發現了錯誤,請先搜尋現有問題,看看是否已被報告。如果尚未報告,請提交新問題,並提供儘可能多的相關資訊。
注意
除錯完問題後,請記住關閉任何已定義的除錯環境變數,或者簡單地啟動一個新的shell以避免受殘留除錯設定的影響。否則,系統可能會因為除錯功能仍然啟用而變慢。
模型下載卡住¶
如果模型尚未下載到磁碟,vLLM 將從網際網路下載它,這可能需要時間並取決於您的網際網路連線。建議先使用 huggingface-cli 下載模型,然後將模型的本地路徑傳遞給 vLLM。這樣,您可以隔離問題。
從磁碟載入模型卡住¶
如果模型很大,從磁碟載入它可能需要很長時間。請注意您儲存模型的位置。有些叢集在節點之間共享檔案系統,例如分散式檔案系統或網路檔案系統,這可能會很慢。最好將模型儲存在本地磁碟中。此外,請檢視 CPU 記憶體使用情況,當模型過大時,它可能會佔用大量 CPU 記憶體,從而降低作業系統的速度,因為它需要頻繁地在磁碟和記憶體之間進行交換。
注意
為了隔離模型下載和載入問題,您可以使用 `--load-format dummy` 引數來跳過載入模型權重。透過這種方式,您可以檢查模型下載和載入是否是瓶頸。
記憶體不足¶
如果模型太大無法放入單個 GPU,您將遇到記憶體不足(OOM)錯誤。考慮採用這些選項來減少記憶體消耗。
生成質量變化¶
在 v0.8.0 中,預設取樣引數的來源在 拉取請求 #12622 中進行了更改。在 v0.8.0 之前,預設取樣引數來自 vLLM 的一組中性預設值。從 v0.8.0 開始,預設取樣引數來自模型建立者提供的 generation_config.json
。
在大多數情況下,這應該會帶來更高質量的響應,因為模型建立者可能知道哪些取樣引數最適合他們的模型。然而,在某些情況下,模型建立者提供的預設值可能會導致效能下降。
您可以透過線上嘗試使用舊的預設值 `--generation-config vllm` 和離線嘗試使用 `generation_config="vllm"` 來檢查是否發生這種情況。如果嘗試後您的生成質量有所提高,我們建議繼續使用 vLLM 預設值,並向 https://huggingface.tw 上的模型建立者請求更新他們的預設 `generation_config.json`,以便產生更高質量的生成。
啟用更多日誌記錄¶
如果其他策略無法解決問題,很可能是 vLLM 例項卡在某個地方。您可以使用以下環境變數來幫助除錯問題
export VLLM_LOGGING_LEVEL=DEBUG
以開啟更多日誌記錄。export CUDA_LAUNCH_BLOCKING=1
以識別是哪個 CUDA 核心導致了問題。export NCCL_DEBUG=TRACE
以開啟 NCCL 的更多日誌記錄。export VLLM_TRACE_FUNCTION=1
用於記錄所有函式呼叫,以便在日誌檔案中檢查,以判斷哪個函式崩潰或掛起。除非絕對需要除錯,否則不要使用此標誌,它會導致啟動時間顯著延遲。
網路設定不正確¶
如果您的網路配置複雜,vLLM 例項可能無法獲取正確的 IP 地址。您可能會在日誌中看到類似 `DEBUG 06-10 21:32:17 parallel_state.py:88] world_size=8 rank=0 local_rank=0 distributed_init_method=tcp://xxx.xxx.xxx.xxx:54641 backend=nccl` 的內容,其中 IP 地址應該是正確的。如果不是,請使用環境變數 `export VLLM_HOST_IP=
您可能還需要設定 `export NCCL_SOCKET_IFNAME=
self.graph.replay()
附近的錯誤¶
如果 vLLM 崩潰並且錯誤跟蹤在 `vllm/worker/model_runner.py` 中的 `self.graph.replay()` 附近捕獲到錯誤,則它是 CUDAGraph 內部的 CUDA 錯誤。要識別導致錯誤的特定 CUDA 操作,您可以在命令列中新增 `--enforce-eager`,或將 `enforce_eager=True` 新增到 LLM 類中,以停用 CUDAGraph 最佳化並隔離導致錯誤的精確 CUDA 操作。
硬體/驅動不正確¶
如果無法建立 GPU/CPU 通訊,您可以使用以下 Python 指令碼並按照下面的說明確認 GPU/CPU 通訊是否正常工作。
程式碼
# Test PyTorch NCCL
import torch
import torch.distributed as dist
dist.init_process_group(backend="nccl")
local_rank = dist.get_rank() % torch.cuda.device_count()
torch.cuda.set_device(local_rank)
data = torch.FloatTensor([1,] * 128).to("cuda")
dist.all_reduce(data, op=dist.ReduceOp.SUM)
torch.cuda.synchronize()
value = data.mean().item()
world_size = dist.get_world_size()
assert value == world_size, f"Expected {world_size}, got {value}"
print("PyTorch NCCL is successful!")
# Test PyTorch GLOO
gloo_group = dist.new_group(ranks=list(range(world_size)), backend="gloo")
cpu_data = torch.FloatTensor([1,] * 128)
dist.all_reduce(cpu_data, op=dist.ReduceOp.SUM, group=gloo_group)
value = cpu_data.mean().item()
assert value == world_size, f"Expected {world_size}, got {value}"
print("PyTorch GLOO is successful!")
if world_size <= 1:
exit()
# Test vLLM NCCL, with cuda graph
from vllm.distributed.device_communicators.pynccl import PyNcclCommunicator
pynccl = PyNcclCommunicator(group=gloo_group, device=local_rank)
# pynccl is enabled by default for 0.6.5+,
# but for 0.6.4 and below, we need to enable it manually.
# keep the code for backward compatibility when because people
# prefer to read the latest documentation.
pynccl.disabled = False
s = torch.cuda.Stream()
with torch.cuda.stream(s):
data.fill_(1)
out = pynccl.all_reduce(data, stream=s)
value = out.mean().item()
assert value == world_size, f"Expected {world_size}, got {value}"
print("vLLM NCCL is successful!")
g = torch.cuda.CUDAGraph()
with torch.cuda.graph(cuda_graph=g, stream=s):
out = pynccl.all_reduce(data, stream=torch.cuda.current_stream())
data.fill_(1)
g.replay()
torch.cuda.current_stream().synchronize()
value = out.mean().item()
assert value == world_size, f"Expected {world_size}, got {value}"
print("vLLM NCCL with cuda graph is successful!")
dist.destroy_process_group(gloo_group)
dist.destroy_process_group()
如果您在單個節點上進行測試,請將 `--nproc-per-node` 調整為您要使用的 GPU 數量
如果您在多節點上進行測試,請根據您的設定調整 `--nproc-per-node` 和 `--nnodes`,並將 `MASTER_ADDR` 設定為主節點的正確 IP 地址,該地址應可從所有節點訪問。然後,執行
NCCL_DEBUG=TRACE torchrun --nnodes 2 \
--nproc-per-node=2 \
--rdzv_backend=c10d \
--rdzv_endpoint=$MASTER_ADDR test.py
如果指令碼成功執行,您應該會看到訊息 `sanity check is successful!`。
如果測試指令碼掛起或崩潰,通常意味著硬體/驅動程式在某種程度上損壞。您應該嘗試聯絡您的系統管理員或硬體供應商以獲取進一步幫助。作為一種常見的變通方法,您可以嘗試調整一些 NCCL 環境變數,例如 `export NCCL_P2P_DISABLE=1`,看看是否有幫助。請查閱它們的文件以獲取更多資訊。請僅將這些環境變數用作臨時解決方案,因為它們可能會影響系統的效能。最好的解決方案仍然是修復硬體/驅動程式,以便測試指令碼能夠成功執行。
注意
多節點環境比單節點環境更復雜。如果您看到諸如 `torch.distributed.DistNetworkError` 之類的錯誤,很可能是網路/DNS 設定不正確。在這種情況下,您可以透過命令列引數手動分配節點排名並指定 IP
- 在第一個節點中,執行 `NCCL_DEBUG=TRACE torchrun --nnodes 2 --nproc-per-node=2 --node-rank 0 --master_addr $MASTER_ADDR test.py`。
- 在第二個節點中,執行 `NCCL_DEBUG=TRACE torchrun --nnodes 2 --nproc-per-node=2 --node-rank 1 --master_addr $MASTER_ADDR test.py`。
根據您的設定調整 `--nproc-per-node`、`--nnodes` 和 `--node-rank`,確保在不同節點上執行不同的命令(帶有不同的 `--node-rank`)。
Python 多程序¶
RuntimeError
異常¶
如果您在日誌中看到類似這樣的警告
WARNING 12-11 14:50:37 multiproc_worker_utils.py:281] CUDA was previously
initialized. We must use the `spawn` multiprocessing start method. Setting
VLLM_WORKER_MULTIPROC_METHOD to 'spawn'. See
https://docs.vllm.tw/en/latest/usage/troubleshooting.html#python-multiprocessing
for more information.
或者 Python 報錯資訊類似這樣
日誌
RuntimeError:
An attempt has been made to start a new process before the
current process has finished its bootstrapping phase.
This probably means that you are not using fork to start your
child processes and you have forgotten to use the proper idiom
in the main module:
if __name__ == '__main__':
freeze_support()
...
The "freeze_support()" line can be omitted if the program
is not going to be frozen to produce an executable.
To fix this issue, refer to the "Safe importing of main module"
section in https://docs.python.club.tw/3/library/multiprocessing.html
那麼您必須更新您的 Python 程式碼,將 `vllm` 的使用置於 `if __name__ == '__main__':` 塊之後。例如,不是這樣
而是嘗試這樣
torch.compile
錯誤¶
vLLM 嚴重依賴 `torch.compile` 來最佳化模型以獲得更好的效能,這引入了對 `torch.compile` 功能和 `triton` 庫的依賴。預設情況下,我們使用 `torch.compile` 來 最佳化模型中的一些函式。在執行 vLLM 之前,您可以透過執行以下指令碼來檢查 `torch.compile` 是否按預期工作
程式碼
如果它從 `torch/_inductor` 目錄引發錯誤,通常意味著您有一個與您正在使用的 PyTorch 版本不相容的自定義 `triton` 庫。例如,請參閱 問題 #12219。
模型檢查失敗¶
如果您看到類似這樣的錯誤
File "vllm/model_executor/models/registry.py", line xxx, in _raise_for_unsupported
raise ValueError(
ValueError: Model architectures ['<arch>'] failed to be inspected. Please check the logs for more details.
這意味著 vLLM 未能匯入模型檔案。通常,這與 vLLM 構建中缺少依賴項或二進位制檔案過時有關。請仔細閱讀日誌以確定錯誤的根本原因。
不支援的模型¶
如果您看到類似這樣的錯誤
Traceback (most recent call last):
...
File "vllm/model_executor/models/registry.py", line xxx, in inspect_model_cls
for arch in architectures:
TypeError: 'NoneType' object is not iterable
或
File "vllm/model_executor/models/registry.py", line xxx, in _raise_for_unsupported
raise ValueError(
ValueError: Model architectures ['<arch>'] are not supported for now. Supported architectures: [...]
但您確定模型在支援模型列表中,那麼 vLLM 的模型解析可能存在一些問題。在這種情況下,請遵循這些步驟來顯式指定模型的 vLLM 實現。
無法推斷裝置型別¶
如果您看到類似 `RuntimeError: Failed to infer device type` 的錯誤,這意味著 vLLM 未能推斷執行時環境的裝置型別。您可以檢視 程式碼,瞭解 vLLM 如何推斷裝置型別以及為什麼它沒有按預期工作。在 此拉取請求 之後,您還可以設定環境變數 `VLLM_LOGGING_LEVEL=DEBUG` 以檢視更詳細的日誌來幫助除錯問題。
NCCL 錯誤:在 ncclCommInitRank
期間發生未處理的系統錯誤¶
如果您的服務工作負載使用 GPUDirect RDMA 進行跨多節點的分散式服務,並在 `ncclCommInitRank` 期間遇到錯誤,即使設定了 `NCCL_DEBUG=INFO` 也沒有清晰的錯誤訊息,它可能看起來像這樣
Error executing method 'init_device'. This might cause deadlock in distributed execution.
Traceback (most recent call last):
...
File "/usr/local/lib/python3.12/dist-packages/vllm/distributed/device_communicators/pynccl.py", line 99, in __init__
self.comm: ncclComm_t = self.nccl.ncclCommInitRank(
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/dist-packages/vllm/distributed/device_communicators/pynccl_wrapper.py", line 277, in ncclCommInitRank
self.NCCL_CHECK(self._funcs["ncclCommInitRank"](ctypes.byref(comm),
File "/usr/local/lib/python3.12/dist-packages/vllm/distributed/device_communicators/pynccl_wrapper.py", line 256, in NCCL_CHECK
raise RuntimeError(f"NCCL error: {error_str}")
RuntimeError: NCCL error: unhandled system error (run with NCCL_DEBUG=INFO for details)
...
這表明 vLLM 未能初始化 NCCL 通訊器,可能是由於缺少 `IPC_LOCK` linux 能力或 `/dev/shm` 未掛載。請參閱分散式推理與服務,獲取關於正確配置分散式服務環境的指導。