๐๏ธ gpuq
A zero-dependency GPU job queue with a live WebUI dashboard and per-task metrics.
Agents and scripts stop racing for the GPU. They submit a job to gpuq โ it queues, schedules, runs, logs, samples GPU/host metrics, and shows everything on a dashboard.
Live WebUI demo ยท ็ฎไฝไธญๆ
What is it?
gpuq is a lightweight, self-hosted GPU task queue for a single machine (or a
machine with many GPUs). Instead of every agent/script doing python main.py directly
and fighting over the GPU, they submit a job โ queue โ schedule โ run โ log โ
metrics โ dashboard โ and let gpuq decide when and where it runs.
- Zero pip dependencies โ pure Python standard library (scheduler, SQLite, HTTP server, CLI, WebUI).
- Priority + VRAM-aware scheduling across any number of GPUs, with automatic GPU allocation.
- Per-task log files โ tail, grep, or view in the browser by task id.
- Per-second GPU telemetry โ utilization, VRAM, temperature, power, SM/memory clocks โ plus optional host network/disk/CPU curves (
psutil). - WebUI dashboard โ live GPU cards, task table (submit/edit/cancel/rerun), time-series charts, and a task detail view with in-window metrics + log viewer.
fallback_waitcrash guard โ a task that dies within N seconds of startup auto-pauses the whole queue so you notice immediately.- Optional
X-Api-Keyauth (enforced as soon asapi_keysis non-empty). - Cross-platform โ Windows / Linux / macOS. Deploys as a Python package, a Docker image, or a
.debwith systemd.
Demo
The WebUI is a static single-page app. The dashboard on GitHub Pages is the real dashboard running against an in-browser simulated backend (4 virtual GPUs, a live task queue, streaming metrics) โ try every feature without installing anything, including submitting tasks, tailing logs, and reading the charts. It degrades gracefully if GitHub Pages is not yet enabled for the repo (the 404 there is harmless).
Installation
pip (PyPI: gpuqu)
The plain
gpuqname is taken on PyPI, so the distribution is published asgpuquthere. The installed console command and import package staygpuq.
pip install gpuqu # core, zero deps
pip install "gpuqu[host]" # + psutil โ host net/disk/cpu charts
This installs the gpuq console command:
gpuq serve # start the server (default http://127.0.0.1:8765)
Or install the latest from source (same package layout):
pip install "gpuqu @ git+https://github.com/Weidows/gpuq.git"
Or run from a checkout without installing: python -m gpuq.cli serve (Python โฅ 3.10).
Docker
docker run -d --name gpuq \
--gpus all \
-p 8765:8765 \
-v gpuq-data:/data \
-v /path/to/work:/work \
ghcr.io/weidows/gpuq:latest
# WebUI: http://localhost:8765
- Requires the NVIDIA Container Toolkit on the host (containerized tasks see the GPUs).
- Tasks run as child processes inside the container; mount training code/data at
/workand submit with"cwd": "/work". docker compose -f packaging/docker/docker-compose.yml up -dgives the full setup (gpus: all, restart policy, health check).
Debian / Ubuntu (.deb)
# Download gpuq_<ver>_all.deb from the GitHub Release
sudo dpkg -i gpuq_*.deb # creates a gpuq user + enables the systemd unit
# WebUI: http://<host>:8765 logs: journalctl -u gpuq -f
Install layout: /usr/bin/gpuq (CLI), /etc/gpuq/config.json, /var/lib/gpuq/ (data),
/etc/systemd/system/gpuq.service.
From source
git clone https://github.com/Weidows/gpuq && cd gpuq
pip install -e . && gpuq serve
Quick start
gpuq serve &
# Submit a job (CLI and REST API are equivalent)
gpuq submit \
--project myexp --user alice --gpu 0 \
--vram 8000 --est 3600 --priority 5 \
--fallback-wait 300 --key my-platform-key \
--version $(git rev-parse --short HEAD) \
-- python main.py --epochs 10 --batch-size 32
gpuq status # queue state + live GPU state
gpuq logs <task_id> --follow # tail a task's log
gpuq list --status running # filter tasks
gpuq metrics --gpu 0 --step 30 # metric series (feed charts / analysis)
gpuq queue pause / resume # pause / resume the whole queue
How it works
agents / CI / cron / scripts
โ POST /api/tasks (CLI `gpuq submit`)
โผ
โโโโโโโโโโโโโโโโโโโ poll every ~2s โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ REST API + WebUI โ โโโโโโโโโโโโโโโโโบ โ Scheduler โ
โ (ThreadingHTTP) โ โ priority โ, created โ, โ
โ X-Api-Key auth โ โ free VRAM โฅ est + headroom โ
โโโโโโโโโโฌโโโโโโโโโ โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโ
โ sqlite3 โ Popen (per-task log file)
โผ โผ
tasks + metrics db GPU tasks (CUDA_VISIBLE_DEVICES injected)
โ
โผ
metric sampler: nvidia-smi (GPU) ยท psutil (host net/disk/cpu, optional)
- Every ~2 s the scheduler picks the highest-priority queued task whose VRAM
estimate fits a free GPU (or its pinned
gpu_id) and starts it as a child process. - A sampler thread records GPU telemetry per second; with
psutilinstalled it adds host network / disk / CPU curves. - When a task exits, its run window gets aggregated (avg/peak utilization, peak VRAM, max temperature, peak power, peak net/disk IO) โ viewable in the WebUI detail page.
Task fields
| Field | Required | Description |
|---|---|---|
command |
โ | Program + args as an array (["python","main.py","--epochs","10"]); with the CLI, put them after -- |
project |
Project name โ grouping/filtering (first dimension of log tracing) | |
username |
Submitter | |
gpu_id |
Pin a GPU index; omit for automatic allocation of the first fitting GPU | |
vram_mb |
Estimated VRAM in MiB โ the scheduling constraint (free VRAM must be โฅ estimate + 512 MB headroom) | |
est_seconds |
Estimated runtime (display only) | |
priority |
Default 5; higher runs sooner | |
fallback_wait_seconds |
Startup crash guard: if the task exits within this many seconds of starting (any exit code), the whole queue auto-pauses with a reason that includes the task id and log path | |
api_key |
Platform key recorded on the task (server-side validation via config api_keys) |
|
version |
Code version / commit for traceability | |
power_limit_w |
Runtime power cap (nvidia-smi -pl; needs root/admin โ failure only warns) |
|
cwd |
Working directory | |
env |
Extra environment variables (dict); CUDA_VISIBLE_DEVICES is injected automatically |
REST API
Base http://<host>:8765; auth header X-Api-Key (enforced only when api_keys is non-empty).
| Method | Path | Description |
|---|---|---|
| POST | /api/tasks (alias /api/submit) |
Submit a task |
| GET | /api/tasks?status=&project=&user=&since=&limit= |
List tasks |
| GET | /api/tasks/{id} |
Detail + aggregated metrics (avg/peak util, VRAM, temp, power, IO) |
| PATCH | /api/tasks/{id} |
Edit a queued task |
| DELETE | /api/tasks/{id} |
Cancel (kills the whole process tree if running) / delete |
| POST | /api/tasks/{id}/rerun |
Clone + re-queue |
| GET | /api/tasks/{id}/logs?offset=&limit=&q= |
Tail / grep the task log |
| GET | /api/tasks/{id}/metrics |
Metric series inside the task's run window |
| GET | /api/metrics?gpu=&from=&to=&step= |
Chart time series (gpu=-1 = host net/disk/cpu) |
| GET | /api/system |
Live GPU + queue state |
| POST | /api/queue/pause / /api/queue/resume |
Pause / resume the queue |
| GET | /api/openapi.json |
Machine-readable endpoint summary (for agent auto-discovery) |
Configuration
config.json (gitignored; template in config.example.json) โ every key can be
overridden by a GPUQ_* env var (GPUQ_PORT, GPUQ_HOST, GPUQ_DATA,
GPUQ_API_KEYS, GPUQ_DEFAULT_POWER_LIMIT, โฆ).
{
"host": "127.0.0.1",
"port": 8765,
"poll_interval": 2.0,
"metrics_interval": 5.0,
"vram_headroom_mb": 512,
"api_keys": [],
"default_power_limit_w": null,
"data_dir": "data"
}
WebUI
- GPU cards โ live utilization, VRAM, temperature, power, SM clock per GPU.
- Charts โ per-GPU utilization / VRAM / temp+power / SM clock over 1h ยท 6h ยท 24h ยท 7d, plus host net/disk/CPU when
psutilis available. - Tasks โ filter tabs by status, submit via form, edit queued jobs, cancel (tree-kill), re-run.
- Task detail โ full metadata, in-window metric chart, and a live-updating log viewer with grep.
Debugging workflow (agent-friendly)
gpuq statusโ is the queue paused (fallback_wait), are GPUs free?gpuq logs <id> --followโ find the error.gpuq metrics --gpu 0 --from <ts>or the WebUI detail page โ read the run window:- OOM โ
peak_memnear the VRAM ceiling; log saysout of memory. - Throttling / overheating โ high
tempwith droppingsm_clockโ lower power cap / change strategy. - IO stall โ
disk_iostuck at 0 while utilization is low. - Network congestion โ
net_rx/net_txpinned at the ceiling.
- OOM โ
- Fix, then
gpuq rerun <id>to re-queue (resume first if paused).
Agent skill
The repo ships a ready-made agent skill at skills/gpuq/SKILL.md โ copy it into your
agent's skill directory:
cp skills/gpuq/SKILL.md ~/.agents/skills/gpuq/SKILL.md
It covers service detection/startup, the full submission-field table, the status โ logs โ metrics โ rerun workflow, CLI + curl examples, and an error-handling table.
Development / CI / Release
pip install -e . && python tests/smoke.py # local smoke test (set GPUQ_SMOKE_FAKE_GPU=1 with no GPU)
- CI (
.github/workflows/ci.yml) โ ubuntu/windows/macos ร py3.10/3.11 matrix: install the wheel โ fake-GPU smoke test โpython -m buildsanity. - Release (
.github/workflows/release.yml, onv*tags) โ GitHub Release assets (wheel + sdist +.deb), aghcr.io/weidows/gpuq:<tag>+latestimage, and PyPI publishing of thegpuqudistribution (skipped unless thePYPI_ENABLEDrepo variable is set โ it is). - GitHub Pages (
.github/workflows/pages.yml, ondocs/**changes) โ publishes the static WebUI demo tohttps://weidows.github.io/gpuq/.
Layout
gpuq/
gpuq/ # config / db / gpu / metrics / scheduler / api / cli / webui (bundled)
docs/ # static WebUI + mock backend โ GitHub Pages live demo
packaging/ # docker/ + deb/ (systemd unit, maintainer scripts)
skills/gpuq/ # agent skill
tests/smoke.py
.github/workflows/ # ci.yml + release.yml + pages.yml
Known limitations & graceful degradation
nvidia-smi -pl(power cap) needs root/admin; on failure it warns and keeps running.- Host net/disk/CPU curves need
psutil(pip install "gpuqu[host]"); without it the corresponding charts are greyed out and everything else keeps working. - Chart.js loads the bundled local vendor file first, falls back to a CDN.
- Multiple GPUs on one host are first-class (per-
gpu_idscheduling); cross-host federation is out of scope for now. - No GPU?
GPUQ_FAKE_GPU=1drives the whole scheduler/metrics path with a synthetic GPU (used by CI).
License
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gpuqu-0.1.3.tar.gz.
File metadata
- Download URL: gpuqu-0.1.3.tar.gz
- Upload date:
- Size: 115.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eac37b66c669ce887c980f19458b8676172fb3cfe53aacc1ee9dddad28879bbe
|
|
| MD5 |
2bf63a8f7d56e3e7614b63d4b1fffe39
|
|
| BLAKE2b-256 |
19b76b654225612bef066bf71b5928f3238dd51ecfcf0ac41c0f0aa6c9d8cb3c
|
Provenance
The following attestation bundles were made for gpuqu-0.1.3.tar.gz:
Publisher:
release.yml on Weidows/gpuq
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gpuqu-0.1.3.tar.gz -
Subject digest:
eac37b66c669ce887c980f19458b8676172fb3cfe53aacc1ee9dddad28879bbe - Sigstore transparency entry: 2490688803
- Sigstore integration time:
-
Permalink:
Weidows/gpuq@798062a9aad2c067f47045d77d6cfdf3c9eae6bb -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/Weidows
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@798062a9aad2c067f47045d77d6cfdf3c9eae6bb -
Trigger Event:
push
-
Statement type:
File details
Details for the file gpuqu-0.1.3-py3-none-any.whl.
File metadata
- Download URL: gpuqu-0.1.3-py3-none-any.whl
- Upload date:
- Size: 113.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ab89700c72433ba2a93b0840b4b864d0dac6cd71ed50ee08492d02c75b04fef
|
|
| MD5 |
d2e12c56eb95ca0e10445df781f1d7fa
|
|
| BLAKE2b-256 |
75afa5c237f19948ec9b64189f8d9185593e54adac4b7de5435d699703fbd1d3
|
Provenance
The following attestation bundles were made for gpuqu-0.1.3-py3-none-any.whl:
Publisher:
release.yml on Weidows/gpuq
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
gpuqu-0.1.3-py3-none-any.whl -
Subject digest:
7ab89700c72433ba2a93b0840b4b864d0dac6cd71ed50ee08492d02c75b04fef - Sigstore transparency entry: 2490688841
- Sigstore integration time:
-
Permalink:
Weidows/gpuq@798062a9aad2c067f47045d77d6cfdf3c9eae6bb -
Branch / Tag:
refs/tags/v0.1.3 - Owner: https://github.com/Weidows
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@798062a9aad2c067f47045d77d6cfdf3c9eae6bb -
Trigger Event:
push
-
Statement type: