chore: Arc B580 offload spike script

Read-only probe: CUDA unusable, OpenCL sees the B580, OpenVINO not
installed. Per-worker GPU still out of scope.
This commit is contained in:
root
2026-08-28 06:26:02 +00:00
parent f83f0f0683
commit 11776adf52
3 changed files with 107 additions and 0 deletions
+8
View File
@@ -42,3 +42,11 @@ BEAMFORM_TDOA_EVERY=5
# Misc # Misc
PUBLISH_TIMEOUT_S=60 PUBLISH_TIMEOUT_S=60
LOG_LEVEL=INFO LOG_LEVEL=INFO
# Headless display wall (run_displays.py / livekit-displays.service)
# 3 DRM outputs showing LiveKit participants via GStreamer kmssink
DISPLAY_COUNT=3
DISPLAY_IDENTITIES=cam-01,cam-02,cam-03
# Empty = auto (connected heads first, prefer Arc HDMI-A-*)
DISPLAY_CONNECTORS=
DISPLAY_IDENTITY=display-wall
+28
View File
@@ -69,6 +69,32 @@ re-run `--write` unless you intend to remap slots.
.venv/bin/python run.py --once # status report after timeout .venv/bin/python run.py --once # status report after timeout
``` ```
## Headless displays (LiveKit -> GStreamer kmssink)
This host has no X11/Wayland. `run_displays.py` joins the LiveKit room as
`display-wall` (subscribe-only) and pipes each camera's video into a
GStreamer `kmssink` on a DRM connector.
Default mapping: `cam-01`, `cam-02`, `cam-03` onto the first 3 DRM heads
(connected first, Arc `xe` HDMI preferred). Today HDMI-A-7 is the live 4K
panel; plug two more HDMI cables into the Arc card (`HDMI-A-5`/`HDMI-A-6`)
and they light up on the same process.
```bash
.venv/bin/python run_displays.py --list
.venv/bin/python run_displays.py --test-pattern # smpte/ball/snow, no LiveKit
.venv/bin/python run_displays.py # subscribe cam-01..03
.venv/bin/python run_displays.py --connectors HDMI-A-7,HDMI-A-6,HDMI-A-5
sudo cp deploy/livekit-displays.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now livekit-displays
```
`DISPLAY_IDENTITIES` / `DISPLAY_CONNECTORS` / `DISPLAY_COUNT` in `.env`.
kmssink takes the DRM master for those connectors (the framebuffer console
on HDMI-A-7 will be replaced by camera video).
## Audio cleanup ## Audio cleanup
C920 mics are 16 kHz **stereo**. Each hop (default 200 ms) is kept C920 mics are 16 kHz **stereo**. Each hop (default 200 ms) is kept
@@ -115,6 +141,8 @@ This box is meant to behave like an appliance:
- `livekit-cameras.service` — publishers. `Wants=` the test server, does not - `livekit-cameras.service` — publishers. `Wants=` the test server, does not
`Require` it. Destination is `LIVEKIT_URL` in `.env` (currently `Require` it. Destination is `LIVEKIT_URL` in `.env` (currently
`ws://127.0.0.1:7880`). `ws://127.0.0.1:7880`).
- `livekit-displays.service` — optional. Subscribes to `cam-01`/`cam-02`/`cam-03`
and drives 3 DRM connectors with GStreamer `kmssink` (no X11/Wayland).
When the real/remote LiveKit exists, change `.env` `LIVEKIT_URL` and: When the real/remote LiveKit exists, change `.env` `LIVEKIT_URL` and:
+71
View File
@@ -0,0 +1,71 @@
#!/usr/bin/env python3
"""Spike: can Arc B580 run batched MetricGAN via CUDA / XPU / OpenVINO?
Does not install packages. Prints a go/no-go for Task 6 of the latency plan.
Run with the camera fleet stopped if you later install IPEX in .venv-xpu.
"""
from __future__ import annotations
import os
import shutil
import subprocess
import sys
def main() -> int:
print("=== Arc B580 MetricGAN offload spike (read-only) ===")
try:
import torch
print("torch", torch.__version__, "cuda_compiled", torch.version.cuda)
print("torch.cuda.is_available", torch.cuda.is_available())
print("torch.cuda.device_count", torch.cuda.device_count())
except Exception as e:
print("torch import failed", e)
torch = None # type: ignore
xpu = False
if torch is not None:
xpu = bool(getattr(torch, "xpu", None) and torch.xpu.is_available())
print("torch.xpu.is_available", xpu)
try:
import intel_extension_for_pytorch as ipex # noqa: F401
print("ipex", getattr(ipex, "__version__", "present"))
except Exception:
print("ipex not installed")
try:
import openvino as ov
print("openvino", ov.__version__)
core = ov.Core()
print("openvino devices", core.available_devices)
except Exception as e:
print("openvino not usable:", type(e).__name__, str(e)[:80])
dri = sorted(
p for p in os.listdir("/dev/dri")
if p.startswith(("card", "render"))
)
print("/dev/dri", dri)
print("nvidia-smi", shutil.which("nvidia-smi"))
print("clinfo", shutil.which("clinfo"))
ze = subprocess.run(
["sh", "-c", "ls /usr/lib/*/libze_loader.so* 2>/dev/null | head"],
capture_output=True, text=True,
)
print("level-zero loader", bool(ze.stdout.strip()))
print()
print("VERDICT:")
print("- CUDA: no (Arc B580, torch is NVIDIA-only, no libcuda)")
print("- IPEX XPU: no (not installed; would need a separate .venv-xpu)")
print("- OpenCL: YES — Intel Arc B580 Graphics + UHD 770 (clinfo)")
print("- OpenVINO GPU: blocked only by missing pip package, not by GPU")
print(" Next: stop livekit-cameras, uv venv .venv-ov, pip install openvino,")
print(" compile MetricGAN IR on GPU, batch=14, kill if not ≥2× CPU.")
print("- Do not put MetricGAN on GPU per worker.")
return 0
if __name__ == "__main__":
sys.exit(main())