Repository navigation
Releases
xpustat 0.7.0
Feature release: xpustat follows a training run from inside the loop, the cluster page streams from every host over one ssh session each, and the server now carries alerts, history and a JSON Schema for its payload.
In a training loop
xpustat.monitor()samples the devices on a thread while your code runs, as a context manager or an iterator, and reports peaks and means per device (peak("util_pct"),mean("mem_used_mb"),summary()).xpustat.callbacks:HFTrainerCallback,LightningCallbackandKerasCallbacklog device metrics to TensorBoard, W&B, MLflow,printor any callable at every logging step. The frameworks are imported only when a callback is constructed; psutil stays the only dependency.
Cluster page
- One streaming ssh session per host: the remote runs
xpustat --json --meta -i Nand the server reads one JSON line per refresh, so the cost no longer grows with a command per host per refresh. Connections are multiplexed withControlMaster; a remote older than 0.7.0 falls back to a command per refresh, and--no-streamforces that path. --history 15m|2hkeeps the sparkline history on the server behind/history, so every tab shows the same history from the moment it opens.--history-file FILE.sqlitewrites a replayable log;xpustat --replay FILE.sqliteplays it back.xpustat --select N --ssh node1 node2 ...and/freepick the freest devices across hosts (xpustat.pick_remote)./metricscovers every host with ahostlabel plusxpustat_host_upandxpustat_host_stale(xpustat.to_prometheus_hosts).- Hosts show their real hostname:
xpustat --json --metawraps the devices in hostname, time and version, and--json -i Nstreams one line per refresh. - Page: fixed column widths so host tables align, a user filter, CSV export, an
older xpustatbadge on hosts that cannot stream.
Alerts
xpustat --checkexits 1 when a device is over--max-temp, under--min-free, reports ECC errors, is throttled or unhealthy, or when a host is down;--no-alert-throttleignores throttling. Works with--hostsand--ssh.- The page shows an alerts bar and sends desktop notifications;
--alert-urlposts new alerts to a webhook,--alert-cooldownkeeps a repeated condition to one message.
Schema and deployment
xpustat --schemaprints a JSON Schema for the payload andxpustat.validate_payloadchecks one. A test holds every vendor's keys to it, which showed that Gaudi, Intel, Huawei, Hygon, Cambricon and Moore Threads emit noprocesseskey; the schema says so.deploy/: Dockerfile, systemd unit, Kubernetes DaemonSet and a Grafana dashboard, documented on a new Deployment page. CI publishes the docs to GitHub Pages.
Fixes
- The ssh control socket path under the macOS temp directory was longer than a Unix socket allows; the sockets now live under
/tmp. - A non-interactive ssh shell has no
~/.local/binon its PATH, so an xpustat installed withuv toolorpip install --userwas invisible to--ssh; the default remote commands add it.
Tested hardware
| Platform | Device |
|---|---|
| Apple | Apple M5, 10-core GPU, macOS 26 |
| NVIDIA | 7x NVIDIA L4 (cc8.9), dual Xeon Silver 4314, Linux |
| AMD | Radeon AI PRO R9700 (gfx1201), ROCm 10.0, Ryzen 9 9950X3D |
| CPU only | Intel N200 (Linux) |
All four were shown on one cluster page over streaming ssh, with one unreachable host alongside; 144 tests pass on macOS and 141 on Linux with 3 skipped. The Windows host was unreachable during this release, so native Windows and WSL were not run this time; CI covers Windows for the tests that need no hardware.
Upgrade
pip install -U xpustatxpustat 0.6.0
Feature release: a browser page for one machine or a whole cluster, served by the exporter with no new dependency, and continuous integration on three platforms.
Web UI
xpustat --uiserveshttp://127.0.0.1:9400/: one self-contained HTML page, nothing loaded from the network, that shows every-acolumn (memory bar, utilization, temperature, power, fan, clocks, P-state, health badges), MIG instances under their GPU, the CPU row with--cpu, and two sparklines per device for the time the tab is open.- Click a device for its detail: UUID, free memory, hotspot and memory temperatures, codec load, ECC counts, throttle reasons, energy, PCIe link, ANE power on Apple, and the processes with PID, user, device memory, SM share, host RSS, CPU share, container or SLURM job and full command line.
- Host, vendor and text filters, a compact mode so forty devices fit on one screen, expand all, pause;
/?expandstarts with every row open. /json,/metricsand the new/clusteranswer on the same port, so one process serves the browser, scripts and Prometheus.--portand--hostset the bind address; the UI binds to loopback by default because the page shows command lines.
Cluster page
xpustat --ui --ssh node1 node2 ...,--hosts http://node:9400 ...or--hosts-file lab.txtput every host on one page with a summary bar: hosts up and down, devices and how many are free, device memory used, processes, the hottest device, throttled and faulted devices.- The server polls the hosts itself on the
-itimer, in parallel, and caches the answer: many open tabs cost one ssh fan-out. A host that stops answering keeps its last snapshot, marked stale with the error; a host that never answered is shown as unreachable; the others are unaffected. - This machine is the first block unless
--no-localis given.--ssh-commandand--timeoutwork as for the terminal cluster view. - From Python:
xpustat.ui.serve_ui()andxpustat.ui.ClusterCollector.
Continuous integration and fixes
- GitHub Actions runs the tests on Ubuntu, macOS and Windows with Python 3.9 and 3.13, a CLI smoke run on a machine without accelerators, the sdist and wheel build,
twine checkand a strict docs build, on every push and pull request. - Prometheus: a textual P-state such as
P2from a plugin backend is exported as 2, and states that are not numbers are skipped instead of raising.
Tested hardware
| Platform | Device |
|---|---|
| Apple | Apple M5, 10-core GPU, macOS 26 |
| NVIDIA | 7x NVIDIA L4 (cc8.9), dual Xeon Silver 4314, Linux |
| AMD | Radeon AI PRO R9700 (gfx1201), ROCm 10.0, Ryzen 9 9950X3D |
| CPU only | Intel N200 (Linux) |
| Windows 11 | Ryzen 7 5800X3D, native Python 3.12 and WSL2 |
All five, plus one unreachable host, were shown on one cluster page polled over ssh; the suite passes on macOS, Linux and native Windows.
Upgrade
pip install -U xpustatxpustat 0.5.0
Feature release: the host CPU as a device, per-process and health detail on NVIDIA and AMD, Apple Silicon sensors without sudo, a cluster view, diagnostics, recording, two new NPU vendors, and a native Windows run.
Host CPU, opt-in
xpustat --cpuandquery_all(include_cpu=True)add one[CPU]row: model, ISA, cores and threads,4P+6Elayout on Apple Silicon, sockets, NUMA nodes, frequency, load average, RAM and swap, temperature and power where the OS exposes them, cgroup limits in containers, and the top processes by resident memory. ThecpuJSON key appears only when asked, so existing output is unchanged.
Processes
- Per-process compute utilization (
sm_pct, from NVML samples ornvidia-smi pmon), memory-bandwidth and codec utilization, full command line (--full-cmd), host RSS and CPU. - Container or job attribution on every process from its cgroup:
docker,containerd,podman, Kubernetes pod, SLURM job. Shown with-k, exported as acontainerlabel.
Health and hardware columns
- NVIDIA and AMD: fan (
-F), SM/graphics and memory clocks (-C), encoder/decoder load (-E), and health (-H): P-state or perf level, active throttle reasons, uncorrected ECC.throttledandhealthyon every device, energy counters where available, PCIe link, power limit. - MIG inventory on the
nvidia-smipath; Jetson engines (NVENC, NVDEC, DLA, ...) andnvpmodelmode. --id 0,2to pick devices,--print-completion bash|zsh|fish.
Apple Silicon
- GPU temperature, GPU power and ANE power without sudo, read in-process from the SMC and the IOReport energy counters; the CPU row gets temperature and power too. Free memory is the OS "available" figure.
Several machines, diagnostics, recording
--hosts http://n1:9400 ...reads other exporters' new/jsonendpoint;--ssh n1 n2runs xpustat over ssh. One table with a host column; an unreachable host never hides the others.--doctorexplains every backend: tool path, probe answer, native binding, env vars, device count, errors.--record FILEwrites one JSON frame per line (gzip optional);--replay FILErenders it.
New backends and fixes
- Rebellions (
rbln-stat --json) and FuriosaAI (furiosa-smi), written from the tools' JSON schemas and awaiting a hardware run;RBLN_DEVICESandFURIOSA_DEVICEShonoured. - Plugin backends through the
xpustat.backendsentry point orregister_backend(). - The optional
amdsmiandnvidia-ml-pybindings no longer breakimport xpustatwhen they fail to load against the installed driver. - Windows: the console is switched to UTF-8 so the table renders on cp1252 consoles, and the CPU model is read from the registry.
- Sole author: Salah Eddine Bekhouche; Hichem Telli is acknowledged for testing the Ascend backend.
Tested hardware
| Platform | Device |
|---|---|
| Apple | Apple M5, 10-core GPU, macOS 26 |
| AMD | Radeon AI PRO R9700 (gfx1201), ROCm 10.0 / amd-smi 27.0, Ryzen 9 9950X3D |
| NVIDIA | 7x NVIDIA L4 (cc8.9), nvidia-smi and nvidia-ml-py paths, dual Xeon Silver 4314 |
| CPU only | Intel N200 (Linux) |
| Windows 11 | Ryzen 7 5800X3D, native Python 3.12: suite, CLI, JSON, doctor |
Upgrade
pip install -U xpustatxpustat 0.4.0
Feature release: the pieces a scheduler or training script needs around the device list, one more NVIDIA form factor, and a way to add vendors from outside the package.
Device selection for the shell
xpustat --select Npicks the N best devices and prints the assignment that restricts a job to them, one line per vendor:CUDA_VISIBLE_DEVICES=1,2,HIP_VISIBLE_DEVICES=0, ... Use it asexport $(xpustat --select 2).--by,--min-freeand--uuidrefine the pick.xpustat.visible_devices_env(devices, format="index"|"uuid")is the library form.TPU_VISIBLE_CHIPS,TT_VISIBLE_DEVICESandNEURON_RT_VISIBLE_CORESare honoured, matching Ray's accelerator managers. Neuron is handled at core level: ranges such as0-3are parsed and a device is visible when any of its cores is.- Every device carries
ray_resource(GPU,NPU,TPU,neuron_cores, ...) andk8s_resource(nvidia.com/gpu,amd.com/gpu,habana.ai/gaudi, ...). Kubernetes names that could not be confirmed areNone.
NVIDIA
- Jetson (
jetson): Nano, Xavier and Orin modules throughtegrastats: shared RAM, GPU load, temperature and the power rail the module exposes. Silent whennvidia-smiexists, so a GPU is never listed twice. Parsers are tested on all three line formats; the backend has not yet been run on a board. - MIG: on the NVML path a GPU in MIG mode lists its compute instances in
mig_instances, with UUID, instance ids, memory and processes. Shown as sub-lines in the CLI and exported as devices to Prometheus. Written from the NVML API; not yet run on a MIG-enabled GPU.
Plugin backends
- A package can add a vendor through the
xpustat.backendsentry point, or at runtime withxpustat.register_backend(name, cls). The vendor then appears inquery_all,to_dict, the CLI,pick_deviceand the exporter. Contract and example indocs/contributing.md.
Query cache
query_all(max_age=seconds)reuses a recent result;--cache-ttldoes the same for--serve-prometheus, for scrapes that arrive faster than the vendor tools answer.
Tested hardware
| Vendor | Device |
|---|---|
| Apple | Apple M5, 10-core GPU, macOS 26 |
| AMD | Radeon AI PRO R9700 (gfx1201), ROCm 10.0 / amd-smi 27.0 |
| NVIDIA | 7x NVIDIA L4 (cc8.9), nvidia-smi and nvidia-ml-py paths |
Upgrade
pip install -U xpustatxpustat 0.3.0
Feature release: four new backends, a vendor-neutral device API for training scripts, and a Prometheus exporter.
New backends
- Apple Silicon (
apple). Read in-process through IOKit, withioregas fallback; about 2 ms per query against 25 ms forioreg. Reports the chip name, GPU core count, utilization and the memory held by the GPU driver. Unified memory meansmem_total_mbis the machine's RAM. Temperature, power and per-process usage are root-only on macOS and are not reported. - AWS Neuron (
neuron) throughneuron-ls --json-output, Google Cloud TPU (tpu) throughtpu-info --format json, and Tenstorrent (tenstorrent) throughtt-smi -s. These are written from the tools' documented output and have not yet been run on hardware; seevendor_devices_tests/to help with that.
Device selection for scripts
- Every device object now has
vendor,device_index,mem_free_mb,framework_indexandtorch_device. xpustat.pick_device()returns the least-loaded devices and honoursCUDA_VISIBLE_DEVICES,HIP_VISIBLE_DEVICES,ASCEND_RT_VISIBLE_DEVICESand the other vendors' variables, so the index it returns is the one the framework will see.
dev = xpustat.pick_device()[0]
model.to(dev.torch_device) # "cuda:2", "npu:0", "mps", ...Prometheus
xpustat --serve-prometheus 9400serves/metricsfor every vendor from one process;xpustat --prometheusprints the text once;xpustat.to_prometheus(stats)is the library form. No new dependencies.
Fixes
- Index access on vendor collections.
stats.amd[0]raisedTypeError; it works as the README has always shown. - Faster vendor commands. The two
nvidia-smiand threeamd-smiinvocations run concurrently: 246 ms to 172 ms on a seven-GPU NVIDIA host, 460 ms to 167 ms on ROCm 10. - Watch mode no longer swallows exceptions.
- Process lines render as
user:command/pidinstead of running user and command together. pip install xpustat[nvidia]now pullsnvidia-ml-py; thepynvmlpackage is deprecated.
Documentation
A docs/ directory with eight pages (installation, CLI, Python API, device selection, Prometheus, backends, contributing) and a mkdocs.yml.
Tested hardware
| Vendor | Device |
|---|---|
| Apple | Apple M5, 10-core GPU, macOS 26 |
| AMD | Radeon AI PRO R9700 (gfx1201), ROCm 10.0 / amd-smi 27.0 |
| NVIDIA | 7x NVIDIA L4 (cc8.9), nvidia-smi and nvidia-ml-py paths |
Upgrade
pip install -U xpustatxpustat 0.2.0
Bug-fix release: AMD GPUs detected again on ROCm 10, and a watch mode that no longer flickers.
Fixes
- AMD detection on ROCm 10. When
amd-smireported a section as"N/A", or an idle GPU returned its process list as a string, the AMD query failed silently and xpustat printed "no accelerators detected". This hit machines with an iGPU next to the discrete card. Both cases are handled now, and each GPU shows whatever fields it reports. - Flicker-free watch mode (
-i). Each frame is rendered in memory and drawn over the previous one in place, on the terminal's alternate screen, so the screen no longer blanks on every refresh. Your terminal is restored on exit. Piped output is unchanged.
Tested hardware
| Vendor | Device |
|---|---|
| AMD | Radeon AI PRO R9700 (gfx1201), ROCm 10.0 / amd-smi 27.0 |
Upgrade
pip install -U xpustatFull changelog: v0.1.0...v0.2.0
xpustat 0.1.0
First release of xpustat — a unified accelerator stat tool in the spirit of gpustat, supporting every major AI accelerator vendor from a single command.
Supported hardware
| Vendor | Device | Status |
|---|---|---|
| NVIDIA | L4 (cc8.9), TITAN V (cc7.0) | ✅ Tested |
| AMD | Radeon RX 7900 XTX (gfx1100) | ✅ Tested |
| Huawei | Ascend 910B2 | ✅ Tested |
| Intel | Gaudi / Gaudi 2 / Gaudi 3 | 🔲 Implemented |
| Intel | Arc / Data Center GPU | 🔲 Implemented |
| Hygon | DCU | 🔲 Implemented |
| Cambricon | MLU | 🔲 Implemented |
| Moore Threads | MTT GPU | 🔲 Implemented |
Install
pip install xpustat
# or
conda install -c conda-forge xpustat
CLI
xpustat # snapshot of all detected devices
xpustat -a # add util, temp, power, arch, processes
xpustat -i 1 # watch mode, refresh every second
xpustat --json # raw JSON output
Python API
import xpustat
stats = xpustat.query_all()
print(stats.amd[0].mem_used_mb)