Repository navigation
[ZenCPU] Add zencpu Platform Runtime Logging and Docs #42726
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
934be93
7fa2107
6ac6b41
f35e221
7555ddc
d24d0dc
8074d81
bc8c57d
6bda06d
0ca058a
04f3971
cffd91a
eea4fb6
aaf22b0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,15 @@ | ||
| <!-- markdownlint-disable MD041 --> | ||
| --8<-- [start:installation] | ||
|
|
||
| vLLM supports basic model inferencing and serving on x86 CPU platform, with data types FP32, FP16 and BF16. | ||
| vLLM supports basic model inferencing and serving on x86 CPU platform, with | ||
| data types FP32 and BF16. | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No reason for line diff here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| On AMD Zen 4 / Zen 5 (Genoa, Bergamo, Turin) CPUs, vLLM auto-activates a | ||
| `ZenCpuPlatform` when a compatible | ||
| [`zentorch`](https://github.com/amd/ZenDNN-pytorch-plugin) package is | ||
| available. For release wheels, install the CPU wheel with the `zen` extra so | ||
| vLLM pulls the tested `zentorch` version for that release. See | ||
| [AMD Zen optimizations](#amd-zen-optimizations) below. | ||
|
|
||
| --8<-- [end:installation] | ||
| --8<-- [start:requirements] | ||
|
|
@@ -216,5 +224,69 @@ docker run --rm \ | |
| ``` | ||
|
|
||
| --8<-- [end:build-image-from-source] | ||
| --8<-- [start:amd-zen-optimizations] | ||
|
|
||
| On AMD Zen CPUs, vLLM auto-selects `ZenCpuPlatform` (a subclass of the default | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again check this file, no need for some of the new lines.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
| `CpuPlatform`) which dispatches linear layers through | ||
| [`zentorch`](https://github.com/amd/ZenDNN-pytorch-plugin)'s ZenDNN-optimized | ||
| kernels. | ||
|
|
||
| #### Install | ||
|
|
||
| ```bash | ||
| export VLLM_VERSION=0.20.2 | ||
| pip install "vllm[zen] @ https://github.com/vllm-project/vllm/releases/download/v${VLLM_VERSION}/vllm-${VLLM_VERSION}%2Bcpu-cp38-abi3-manylinux_2_35_x86_64.whl" \ | ||
| --extra-index-url https://download.pytorch.org/whl/cpu | ||
| ``` | ||
|
|
||
| This keeps the vLLM CPU wheel and `zentorch` on the tested version combination, | ||
| instead of installing `zentorch` separately and risking dependency skew. | ||
| That's it - no flag or env var is required. vLLM's platform discovery picks up | ||
| `ZenCpuPlatform` automatically the next time `vllm` is imported. | ||
|
|
||
| #### Detection rules | ||
|
|
||
| `ZenCpuPlatform` is selected when **all** of the following hold: | ||
|
|
||
| - vLLM is built for CPU | ||
| - `/proc/cpuinfo` reports `AuthenticAMD` and `avx512`. | ||
| - `import zentorch` succeeds. | ||
|
|
||
| Otherwise, vLLM falls back to the default `CpuPlatform` (oneDNN/sgl-kernel | ||
| paths). | ||
|
|
||
| #### Supported dtypes | ||
|
|
||
| `ZenCpuPlatform.supported_dtypes` advertises only `bfloat16` and `float32`. | ||
| Models declared with `torch_dtype=float16` are auto-downcast to `bfloat16` at | ||
| load time with the standard | ||
| `"Your device 'cpu' doesn't support torch.float16. Falling back to torch.bfloat16 for compatibility."` | ||
| warning emitted from `vllm/config/model.py`. | ||
|
|
||
| #### Verify it is engaged | ||
|
|
||
| Run any model with INFO-level logs and grep for the activation banner: | ||
|
|
||
| ```bash | ||
| VLLM_LOGGING_LEVEL=INFO vllm serve facebook/opt-125m --dtype bfloat16 \ | ||
| 2>&1 | grep -E "ZenCpuPlatform activated|CPU unquantized GEMM dispatch" | ||
| ``` | ||
|
|
||
| You should see one line confirming `ZenCpuPlatform activated` (with the | ||
| `zentorch` version, `VLLM_ZENTORCH_WEIGHT_PREPACK` value, and AVX-512 / | ||
| AVX-512_BF16 capability flags) and one line confirming each unquantized linear | ||
| layer is routed through `zentorch_linear_unary`. | ||
|
|
||
| #### Environment variables | ||
|
|
||
| - `VLLM_ZENTORCH_WEIGHT_PREPACK` (default `1`): when set, eagerly prepacks | ||
| linear weights into ZenDNN's blocked layout at model load time, eliminating | ||
| per-inference layout conversion overhead. Set to `0` to disable. | ||
|
|
||
| #### Reference | ||
|
|
||
| For the design rationale, see [RFC #35089: In-Tree AMD Zen CPU Backend via zentorch](https://github.com/vllm-project/vllm/issues/35089). | ||
|
|
||
| --8<-- [end:amd-zen-optimizations] | ||
| --8<-- [start:extra-information] | ||
| --8<-- [end:extra-information] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,11 +2,15 @@ | |
| # SPDX-FileCopyrightText: Copyright contributors to the vLLM project | ||
| """Tests for CPU unquantized GEMM dispatch behavior.""" | ||
|
|
||
| import sys | ||
| import types | ||
|
|
||
| import pytest | ||
| import torch | ||
|
|
||
| from vllm.model_executor.layers import utils | ||
| from vllm.platforms import current_platform | ||
| from vllm.platforms import zen_cpu | ||
|
|
||
|
|
||
| @pytest.fixture(scope="module") | ||
|
|
@@ -66,3 +70,67 @@ def test_dispatch_cpu_unquantized_gemm_zen_remove_weight(monkeypatch): | |
| utils.dispatch_cpu_unquantized_gemm(layer, remove_weight=True) | ||
|
|
||
| assert layer.weight.numel() == 0 | ||
|
|
||
|
|
||
| @pytest.mark.usefixtures("_mock_zentorch_linear_unary") | ||
| def test_dispatch_cpu_unquantized_gemm_logs_zentorch_dispatch(monkeypatch): | ||
|
Comment on lines
+71
to
+72
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this be skipped if platform is not zen_cpu?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, this is intentional. The test is a unit test for the dispatcher logic. It uses the Skipping on non-Zen hardware would mean the new logging code is never validated in CI. The pattern matches the two existing tests above it (
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. although, would love to get your thoughts on adding UT for logging |
||
| monkeypatch.setattr(current_platform, "is_zen_cpu", lambda: True) | ||
| expected_prepacked = bool(utils.envs.VLLM_ZENTORCH_WEIGHT_PREPACK) and hasattr( | ||
| torch.ops.zentorch, "zentorch_weight_prepack_for_linear" | ||
| ) | ||
|
|
||
| log_calls = [] | ||
| monkeypatch.setattr(utils.logger, "info_once", lambda *args: log_calls.append(args)) | ||
|
|
||
| layer = torch.nn.Linear(16, 8, bias=True) | ||
| utils.dispatch_cpu_unquantized_gemm(layer, remove_weight=False) | ||
|
|
||
| assert log_calls == [ | ||
| ( | ||
| "CPU unquantized GEMM dispatch: using zentorch_linear_unary " | ||
| "(prepacked=%s)", | ||
| expected_prepacked, | ||
| ) | ||
| ] | ||
|
|
||
|
|
||
| def test_zen_cpu_platform_logs_activation(monkeypatch): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same answer as the previous one |
||
| fake_zentorch = types.SimpleNamespace( | ||
| __version__="5.2.1", | ||
| __config__="zentorch build config", | ||
| ) | ||
| monkeypatch.setitem(sys.modules, "zentorch", fake_zentorch) | ||
| monkeypatch.setattr(zen_cpu.envs, "VLLM_ZENTORCH_WEIGHT_PREPACK", 1) | ||
| monkeypatch.setattr(zen_cpu.torch.cpu, "_is_avx512_supported", lambda: True) | ||
| monkeypatch.setattr( | ||
| zen_cpu.torch.cpu, "_is_avx512_bf16_supported", lambda: False | ||
| ) | ||
|
|
||
| log_calls = [] | ||
| monkeypatch.setattr( | ||
| zen_cpu.logger, "info_once", lambda *args: log_calls.append(args) | ||
| ) | ||
|
|
||
| def fake_check_and_update_config(cls, vllm_config): | ||
| pass | ||
|
|
||
| monkeypatch.setattr( | ||
| zen_cpu.CpuPlatform, | ||
| "check_and_update_config", | ||
| classmethod(fake_check_and_update_config), | ||
| ) | ||
|
|
||
| zen_cpu.ZenCpuPlatform.check_and_update_config(object()) | ||
|
|
||
| assert log_calls == [ | ||
| ( | ||
| "ZenCpuPlatform activated | zentorch=%s | " | ||
| "VLLM_ZENTORCH_WEIGHT_PREPACK=%d | " | ||
| "AVX-512=%s | AVX-512_BF16=%s", | ||
| "5.2.1", | ||
| 1, | ||
| True, | ||
| False, | ||
| ), | ||
| ("zentorch build config: %s", "zentorch build config"), | ||
| ] | ||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
| @@ -1,13 +1,21 @@ | ||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||
| # SPDX-FileCopyrightText: Copyright contributors to the vLLM project | ||||||||
|
|
||||||||
| from typing import TYPE_CHECKING | ||||||||
|
|
||||||||
| import torch | ||||||||
|
|
||||||||
| from vllm import envs | ||||||||
| from vllm.logger import init_logger | ||||||||
| from vllm.platforms.cpu import CpuPlatform | ||||||||
|
|
||||||||
| logger = init_logger(__name__) | ||||||||
|
|
||||||||
| if TYPE_CHECKING: | ||||||||
| from vllm.config import VllmConfig | ||||||||
| else: | ||||||||
| VllmConfig = None | ||||||||
|
|
||||||||
|
|
||||||||
| class ZenCpuPlatform(CpuPlatform): | ||||||||
| """CPU platform with AMD Zen (ZenDNN/zentorch) optimizations. | ||||||||
|
|
@@ -30,3 +38,27 @@ def is_zen_cpu(self) -> bool: | |||||||
| @property | ||||||||
| def supported_dtypes(self) -> list[torch.dtype]: | ||||||||
| return [torch.bfloat16, torch.float32] | ||||||||
|
|
||||||||
| @classmethod | ||||||||
| def check_and_update_config(cls, vllm_config: VllmConfig) -> None: | ||||||||
| super().check_and_update_config(vllm_config) | ||||||||
|
|
||||||||
| import zentorch | ||||||||
|
|
||||||||
| zentorch_version = getattr(zentorch, "__version__", "unknown") | ||||||||
| avx512 = torch.cpu._is_avx512_supported() | ||||||||
| avx512_bf16 = torch.cpu._is_avx512_bf16_supported() | ||||||||
|
|
||||||||
| logger.info_once( | ||||||||
| "ZenCpuPlatform activated | zentorch=%s | " | ||||||||
| "VLLM_ZENTORCH_WEIGHT_PREPACK=%d | " | ||||||||
| "AVX-512=%s | AVX-512_BF16=%s", | ||||||||
| zentorch_version, | ||||||||
| int(envs.VLLM_ZENTORCH_WEIGHT_PREPACK), | ||||||||
| avx512, | ||||||||
| avx512_bf16, | ||||||||
| ) | ||||||||
|
|
||||||||
| zentorch_config = getattr(zentorch, "__config__", None) | ||||||||
| if zentorch_config: | ||||||||
| logger.info_once("zentorch build config: %s", zentorch_config) | ||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. check_and_update_config is not the right place to print info banners. We already have logging that the zen platform is being used here - perhaps upgrade that logging level to info instead? vllm/vllm/platforms/__init__.py Lines 190 to 192 in 02606b0
|
||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would put this above the "How to decide
VLLM_CPU_OMP_THREADS_BIND"There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done