diff options
| author | Danilo M. <danix@danix.xyz> | 2026-07-06 18:34:31 +0200 |
|---|---|---|
| committer | Danilo M. <danix@danix.xyz> | 2026-07-06 18:34:31 +0200 |
| commit | fc78b51e29497703a65f125e844f7da558dbc577 (patch) | |
| tree | 5e5e3eb3c79b823971d4577d86684d154d127341 /README.md | |
| download | imggen-fc78b51e29497703a65f125e844f7da558dbc577.tar.gz imggen-fc78b51e29497703a65f125e844f7da558dbc577.zip | |
Initial commit: local SDXL image generation on Intel Arc B580
Containerized SDXL-base generation targeting a 12GB Arc B580 under
Slackware. The container carries the Intel Level Zero runtime the host
distro does not package; the fp16-fix VAE removes the fp32 upcast that
would otherwise OOM at decode.
- imggen: host wrapper (GPU passthrough, /out bind-mount, model cache)
- generate.py: in-container XPU pipeline, scope-bounded to SDXL base
- Dockerfile: pinned to the known-good torch-XPU / diffusers stack
- README.md, CLAUDE.md: rationale, limits, and version-pinning notes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..d52dbeb --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# imggen + +Local SDXL image generation on an Intel Arc B580 (12GB) under Slackware, via a +container that carries the Intel Level Zero runtime the host distro does not +package. Prompt in, PNG on the host out. + +## Why this exists (and its limits) + +The Arc B580 runs SDXL's *compute* fast (~31 UNet it/s warm), but its *memory* +is tight. Stock SDXL fp16 OOMs at VAE decode on 12GB because diffusers upcasts +the VAE to fp32. Swapping in the fp16-fix VAE removes that upcast and the whole +pipeline fits, at roughly 6.3s per warm 1024x1024 image, 25 steps. + +Measured peak VRAM for the working config is 9.07 GB on a 12GB card, so there +is roughly 2.5-3 GB of real headroom, not zero. + +Known to work: + +- SDXL base, single image, 1024x1024, ~25 steps. ~6.3s warm. + +Plausibly fits in the remaining headroom (UNTESTED, try before assuming): + +- A second batched image, or modest resolution bumps above 1024. +- Light img2img. + +Probably does NOT fit (a second resident model exceeds ~3GB): + +- SDXL refiner co-resident with base. + +Does NOT fit: + +- Flux (any variant). Far heavier than the available margin. + +If you want the refiner or Flux, that is the signal to move that tier of work +to a RunPod serverless endpoint rather than fighting 12GB. Local covers the +light case comfortably and may stretch a little past it; it does not reach the +heavy tier. + +## Build + +The Dockerfile is PINNED to the exact versions captured from the known-good +test container (torch 2.12.1+xpu, diffusers 0.39.0, transformers 5.13.0, etc., +on oneAPI 2025.3.2 / Ubuntu 24.04.4). These produced ~6.3s warm SDXL-base +images with 9.07 GB peak VRAM on an Arc B580. + +Build: + +``` +docker build -t imggen:local . +``` + +If the base image tag `intel/oneapi-basekit:2025.3.2-0-devel-ubuntu24.04` is +not available on Docker Hub, substitute the closest 2025.3.x tag and record +what you used. Do not fall back to `:latest`. + +## Install the wrapper + +``` +cp imggen ~/bin/imggen # or anywhere on your PATH +chmod +x ~/bin/imggen +``` + +## Usage + +``` +imggen "a red bicycle against a stone wall" +imggen "a foggy harbour at dawn" --steps 30 --seed 42 +imggen "portrait of a fox" -o fox.png -n "blurry, low quality" +``` + +Output lands in `~/imggen-out` by default. Models cache in +`~/.cache/imggen-models` so the ~7.5GB download happens once. + +Override paths with env vars: + +``` +IMGGEN_OUT=/srv/blog/img IMGGEN_CACHE=/mnt/models imggen "a lighthouse" +``` + +## First run + +The first invocation downloads SDXL base + the fp16-fix VAE (~7.5GB) into the +cache volume. That run is network-bound and slow. Subsequent runs skip the +download. The first *generation* in any fresh container is also slower (~7.3s) +due to one-time kernel compilation; warm runs settle to ~6.3s. + +## Upgrading + +Treat upgrades as deliberate, tested events. Do not `pip install -U` casually. +This working state depends on a specific torch-XPU build, a specific diffusers +version, and the fp16-fix VAE. If you rebuild with newer versions, keep the old +pinned Dockerfile in git so you can revert when something breaks. + +## Trial + +This is a time-boxed experiment. Run it against real blog work for a few weeks. +If it sticks, keep it. If it does not, the fallback is a RunPod serverless +ComfyUI endpoint wrapped in the same `imggen` CLI shape, which trades local +privacy for the ability to run heavier models (Flux, refiner, batching) +on-demand at zero idle cost. |
