diff --git a/README.md b/README.md index 2b8622a1..536e7e6e 100644 --- a/README.md +++ b/README.md @@ -838,7 +838,7 @@ The device comes from what the cluster advertises, not from the host alone: | Cluster has | Device | Pod gets | |-------------|--------|----------| -| allocatable `habana.ai/gaudi` | `HPU` | one Gaudi, served by vLLM (see [vLLM on Gaudi](#vllm-on-gaudi)) | +| allocatable `habana.ai/gaudi` | `HPU` | one Gaudi, served by vLLM, not yet run on Gaudi hardware (see [vLLM on Gaudi](#vllm-on-gaudi)) | | allocatable `gpu.intel.com/xe`, else `gpu.intel.com/i915`, on a node labelled `gpu.intel.com/xmx=true`, skipping a driver labelled `k3d-gpu.io/xmx.=false` | `GPU` | one GPU, a `gpu.intel.com/xmx: "true"` node selector; the host render group is added as a supplemental group | | anything else, including an Intel GPU without XMX (or with `xmx` unknown) | `CPU` | no device; the P-cores on a hybrid node; on a node labelled `...cpu-cpuid.AMXTILE=true` it is pinned there | | `npu.intel.com/accel`, only with `K3D_GPU_AGENT_DEVICE=NPU` | `NPU` | the NPU and its accel node's group | @@ -977,8 +977,8 @@ OpenAI API at `/v1` from `svc/vllm`: | Backend | Image (pinned by digest) | Notes | |---------|--------------------------|-------| -| `vllm` | `vllm/vllm-openai-xpu:v0.32.0` | upstream vLLM for Intel GPUs (Data Center GPU and Arc, per [vLLM's XPU guide](https://github.com/vllm-project/vllm/blob/v0.32.0/docs/getting_started/installation/gpu.xpu.inc.md)); v0.32.0 not yet run here on an Arc B-series card | -| `llm-scaler` | `intel/llm-scaler-vllm:1.5` (vLLM 0.26.0-b2) | Intel's build for Arc B60/B70 | +| `vllm` | `vllm/vllm-openai-xpu:v0.32.0` | upstream vLLM for Intel GPUs (Data Center GPU and Arc, per [vLLM's XPU guide](https://github.com/vllm-project/vllm/blob/v0.32.0/docs/getting_started/installation/gpu.xpu.inc.md)); served end to end here on an Arc Pro B70 at release 0.1.94 (status below) | +| `llm-scaler` | `intel/llm-scaler-vllm:1.5` (vLLM 0.26.0-b2) | Intel's build for Arc B60/B70; not yet run here on hardware (status below) | ```bash K3D_GPU_AGENT_BACKEND=vllm k3d-gpu agent up @@ -1000,9 +1000,39 @@ other backend first so its GPU is free; `agent down` and `agent status` cover bo The chat UI below and other clients that use `svc/ovms` at `/v3` need `http://vllm.k3d-gpu-agent.svc:8000/v1` instead. -Not yet run on Arc hardware here: serving end to end and tensor parallelism -above 1 (`CCL_ZE_IPC_EXCHANGE=pidfd`; oneCCL calls `prctl(PR_SET_PTRACER, getppid())`, -so sibling workers should need no `CAP_SYS_PTRACE` under yama `ptrace_scope=1`). +**Status: `vllm` is verified end to end on an Arc Pro B70 at release 0.1.94.** On +2026-11-08, release 0.1.94, installed by the public `packaging/install.sh`, ran +`k3d-gpu up` and `K3D_GPU_AGENT_BACKEND=vllm k3d-gpu agent up` with the defaults and no +patching: `vllm/vllm-openai-xpu:v0.32.0` (vLLM 0.32.0, digest `sha256:20509fab...`) +serving `Qwen/Qwen3-4B` at revision `1cfa9a72`. The pod was Ready on one card +(`gpu.intel.com/xe: 1`) and the launcher's warm-up was answered. Through the +port-forward `agent up` prints, "What is 17 times 23?" came back 391, and the `hermes` +parser returned the tool call. The host was a Xeon 6741P with 4x Arc Pro B70 (`xe`, +kernel 7.0.0-31, Ubuntu 26.04.1). The same checks passed in the same hold on the +`v0.33.0` bump's head ([#357](https://github.com/88plug/k3d-gpu/pull/357)). Record, with +every version and file: +[bench/vllm-agent/results/2026-11-08](bench/vllm-agent/results/2026-11-08/README.md). + +Releases 0.1.21 (2026-10-16) through 0.1.93 do not serve with vLLM, on Arc or on a +Gaudi, and neither does `agent up --model` when the fit picks vLLM. The hardware canary +for the `v0.33.0` bump ([#326](https://github.com/88plug/k3d-gpu/pull/326)) found two +causes on an Arc Pro B70 on 2026-11-07; the `v0.32.0` image exits there on the first one +too: + +- The Service is named `vllm`, so Kubernetes gives the pod + `VLLM_PORT=tcp://:8000`. vLLM reads `VLLM_PORT` as its own port and exits + at engine start ("appears to be a URI"), and the pod crash-loops. +- The warm-up posts through the API server's service proxy with no `Content-Type`, and + vLLM answers such a request with 400. + +[#339](https://github.com/88plug/k3d-gpu/pull/339) fixed both in 0.1.94: the pod spec +sets `enableServiceLinks: false`, and the warm-up runs curl inside the pod with +`Content-Type: application/json`. llm-scaler and the Gaudi image are built on vLLM 0.26 +and 0.30, whose upstream source has both checks, and they get the same pod spec and +warm-up; neither has run on hardware yet. Tensor parallelism above 1 has not run on +Arc hardware either (`CCL_ZE_IPC_EXCHANGE=pidfd`; oneCCL calls +`prctl(PR_SET_PTRACER, getppid())`, so sibling workers should need no `CAP_SYS_PTRACE` +under yama `ptrace_scope=1`). | Variable | Default | Description | |----------|---------|-------------| @@ -1039,7 +1069,11 @@ for tensor parallelism and Qwen models, `SYS_NICE`, an 8 GiB memory-backed bounds the HPU warm-up, which runs on every start and takes minutes; `K3D_GPU_AGENT_TIMEOUT` (1800 s) bounds it. -Not yet run on Gaudi hardware here: serving end to end. The device plugin runs +Not yet run on Gaudi hardware here: serving end to end. Releases up to 0.1.93 do not +serve it: the Gaudi pod shares the Arc pod spec and warm-up, and with them the +[two faults above](#vllm-backends-for-discrete-arc-battlemage) that +[#339](https://github.com/88plug/k3d-gpu/pull/339) fixed in 0.1.94, whose end-to-end +check ran on an Arc Pro B70 only. The device plugin runs without Intel's `habana-container-runtime` hook (see `share/gaudi-device-plugin.yml`), so whether vLLM opens the HPU with only the plugin's device nodes and environment is unverified. vllm-gaudi validates `Qwen3-0.6B`, not `Qwen3-4B`, and tensor diff --git a/bench/vllm-agent/results/2026-11-08/README.md b/bench/vllm-agent/results/2026-11-08/README.md new file mode 100644 index 00000000..4b8c62b5 --- /dev/null +++ b/bench/vllm-agent/results/2026-11-08/README.md @@ -0,0 +1,77 @@ +# The vLLM agent on an Arc Pro B70, unpatched (2026-11-08) + +The end state of `K3D_GPU_AGENT_BACKEND=vllm k3d-gpu agent up` on one Arc Pro B70, through +the launcher alone: no `kubectl patch`, no warm-up sent by hand, the default image and +model. Two launchers ran in one hold: + +- `main-0.1.94`: release 0.1.94, the first release with + [#339](https://github.com/88plug/k3d-gpu/pull/339) (no Service links in the pod, and + the warm-up sent from inside the pod as JSON). +- `pr357-0985b179`: the head of [#357](https://github.com/88plug/k3d-gpu/pull/357), which + moves the image to `v0.33.0`. That head was regenerated onto main after #339 merged. + +Both passed. Releases 0.1.21 through 0.1.93 do not serve with vLLM: their Service gives +the pod `VLLM_PORT=tcp://...`, on which vLLM exits, and their warm-up reaches vLLM with no +`Content-Type`, which it answers with 400. + +This record covers vLLM XPU on Arc only. The Gaudi path and llm-scaler have not run on +hardware, and neither has tensor parallelism above 1. + +## Host + +crescent: Xeon 6741P, 4x Arc Pro B70 on the `xe` driver, kernel `7.0.0-31-generic`, Ubuntu +26.04.1 LTS. The hold took `~/k3dgpu-bench.lock`. It freed the cards by stopping +`qwen38-a-hr`, `qwen38-b-hr` and `aiperf010` with `docker stop -t 120`, after a snapshot, +a check that neither server had a request in the last 10 minutes, and each server's +baseline answer ("Paris"). Afterwards it started them again, and both servers gave the same +answer. All four cards read 0 GiB before each run and after each teardown. + +## Launchers and versions + +| | `main-0.1.94` | `pr357-0985b179` | +|---|---|---| +| Launcher | `/usr/bin/k3d-gpu` 0.1.94 from `k3d-gpu_0.1.94-1_all.deb` (sha256 `60a1dc5bbc5e6f2a439c34c9ec19dc2c916dcd35c5bec9d46752ee2ebcfd8dec`, the `aur-v0.1.94` release asset) | `scripts/k3d-gpu` 0.1.95 from a clean checkout of `0985b17902e507b13d8460970fbe2a15051ac5c9` (sha256 `e2d97e1960a04516d83ddc1c21c4142a406a2be6797ca1f102bd5feb1b495438`) | +| How installed | `packaging/install.sh` from main at `e5f55b29` (sha256 `62c30da91025f5af25557e5e49da8c496591d98f3fb0f9a393c673b65edbbc55`), which pins 0.1.94; it also put k3d v5.9.0 and kubectl v1.37.2 in `~/.local/bin` | `scripts/checkout.sh` (`git fetch --depth 1` of the commit, no changes) | +| Node image | `cryptoandcoffee/k3d-gpu:0.1.94` (`sha256:8630e14556e70111a097dcf22d15a7484bc94fa19a2d4b04b311ec60778d438e`) | `cryptoandcoffee/k3d-gpu:0.1.95` (`sha256:65499cbe202dca63c28029e03c4eb5139f5de31f5f369d915494f06e6f4dd3fa`) | +| Agent image | `vllm/vllm-openai-xpu:v0.32.0@sha256:20509fabe50dda62c09c0786d1a6effa299d3dbdddcc49331b93e65144652a8c`, vLLM 0.32.0 | `vllm/vllm-openai-xpu:v0.33.0@sha256:be3a9aea234be64ffc2816ac561c597e0f0b1f44a61a7f4912780e4d77450086`, vLLM 0.33.0 | +| Model | `Qwen/Qwen3-4B` at `1cfa9a7208912126459214e8b04321603b3df60c`, float16, `hermes` tool parser, `qwen3` reasoning parser | the same | + +The release package and the k3d and kubectl binaries the installer added were removed after +the hold (`install-0.1.94/after-uninstall.txt`). + +## Results + +| | `main-0.1.94` | `pr357-0985b179` | +|---|---|---| +| `k3d-gpu up` | rc 0 in 48 s, allocatable `gpu.intel.com/xe: 4` | rc 0 in 49 s, the same | +| `agent up` | rc 0 in 255 s | rc 0 in 258 s | +| Pod | Ready, 0 restarts, limits `gpu.intel.com/xe: 1`, `enableServiceLinks: false`, no `VLLM_PORT` in its environment, one render node (`renderD129`) | the same, `renderD128` | +| VRAM while serving | 27.50 GiB on 0000:48:00.0, 0 on the other three cards | 27.30 GiB on 0000:12:00.0, 0 on the other three | +| KV cache (vLLM's log) | 137,472 tokens | 131,776 tokens | +| The launcher's warm-up line | `warm-up reply (2s): I am a large language model developed by Alibaba Cloud.` | the same | +| "What is 17 times 23?" | `391` (ends `\boxed{391}`), finish `stop`, 1,426 completion tokens (1,283 reasoning), 22.7 s | the same | +| Tool call | `get_weather` with arguments `{"city": "Paris"}`, finish `tool_calls`, 1.6 s | the same | +| Teardown | `agent down` and `down` rc 0, 0 GiB on all four cards, no k3d containers left | the same | +| `run.sh` verdict | PASS | PASS | + +Both requests went through the endpoint `agent up` prints +(`kubectl -n k3d-gpu-agent port-forward svc/vllm 8000:8000`). The chat request had no +system prompt, thinking left on, temperature 0 and `max_tokens` 4096. The tool request +offered one function, `get_weather(city)`, with "What is the weather in Paris right now?" +and `tool_choice: auto`. `run.sh` passes a run only when the pod is Ready with one +`gpu.intel.com/xe`, the launcher printed its warm-up reply, the chat answer contains 391, +and the tool call is `get_weather` with `city` Paris. + +## Files + +| Path | What | +|---|---| +| `hold.log` | The hold, in order: the lock, the services stopped, each run's driver lines, the restart and the baseline answers | +| `takeover-restore.txt` | The stop and restart logs of the three services, and the names stopped | +| `queue` | The runs the hold took, as `