1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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.
|