Local AI Image Generation on an AMD Mini PC: ComfyUI + Z-Image Turbo

Posted
July 11, 2026
By
Jacob Lloyd — written with AI assistance, post-project
Read time
7 min read

In plain terms: How I set up my small AMD computer to create AI-generated images at home — about 27 seconds per picture, with no subscription and no per-image fee. The guide walks through the setup so it starts automatically and just works. It proves you don't need an expensive cloud service or a specific graphics card brand to make AI art.

My mini PC turns a text prompt into a finished 1024×1024 image in about 27 seconds: no cloud account, no per-image charge, no queue behind a thousand other people's prompts. And it's an AMD chip most people assume can't do this at all.

TL;DR

  • What it is: ComfyUI + Z-Image Turbo, generating images entirely on local hardware — OpenAI and Midjourney are nowhere in the loop.
  • What it costs: $0 per image, however many you make. There isn't even an account to sign up for.
  • What you need: an AMD APU or GPU with real VRAM (mine has 64GB), a Linux box, and one session of ROCm setup pain. Once.
  • What you end up with: ~27 seconds per 1024×1024 image, an always-on systemd service, and a one-line command to batch-generate images headless.

What you end up with

The setup talk can wait. Day to day, I open a browser tab or fire it off from a terminal. Either way:

MetricValue
Resolution1024×1024
Steps / CFG8 steps, CFG 1.0
Warm generation time~27s (measured range: 26.5–30.4s)
Cold start (first image after boot)~43.5s while ~20GB of weights load

The real use case on this box isn't art for art's sake. It's a script that batch-generates avatar variations for a chatbot project: 222 PNGs in the output folder and counting. Boring, reliable infrastructure, which is exactly what you want from something you built for fun and then started depending on.

The hardware

This is a 128GB unified-memory box: an AMD Ryzen AI Max+ 395 ("Strix Halo") with a Radeon 8060S iGPU on the same package as the CPU. No discrete GPU anywhere.

Here's the part that matters. Firmware carves out 64 GiB of that 128GB and hands it to the iGPU as dedicated "VRAM" — ComfyUI's own startup log reads Total VRAM 65536 MB, total RAM 63920 MB. That's more VRAM than any consumer NVIDIA card sells, because it isn't expensive GDDR soldered to a graphics card. It's just system memory the firmware assigned to the GPU, with another ~31GB of GPU-accessible GTT behind it if needed.

ComponentSpec
CPUAMD Ryzen AI Max+ 395, 16 cores / 32 threads
iGPURadeon 8060S, ROCm arch gfx1151
Memory128GB unified LPDDR5X — 64GiB carved out as VRAM, ~62GiB left for Linux
OSBazzite (immutable, Fedora Silverblue based)
Discrete GPUNone

The model weights for this whole setup add up to about 20.7GB. Comfortable inside 64GB; hopeless on a typical 8–16GB consumer card unless you offload layers to system RAM and eat the speed penalty.

Software stack

The versions that make this work, as installed right now:

ComponentVersion
ComfyUIv0.27.0 (git checkout)
Python3.12.13, in a venv built with uv
PyTorch2.12.1+rocm7.2
torchvision0.27.1+rocm7.2
torchaudio2.11.0+rocm7.2
pytorch-triton-rocm3.5.1
ROCm7.2, native gfx1151 support

The fun detail: ROCm's PyTorch build masquerades as CUDA. The startup log literally says Device: cuda:0 AMD Radeon 8060S : native. Python written for an NVIDIA card just runs, because it thinks it's talking to one. ComfyUI also auto-disables cuDNN on this hardware and falls back to plain PyTorch attention (no xformers, no flash-attn), and it works fine without them.

Getting ROCm to behave

The setup pain lives in a handful of environment variables in the launch script:

HSA_OVERRIDE_GFX_VERSION=11.5.1
PYTORCH_HIP_ALLOC_CONF=expandable_segments:True
HIP_VISIBLE_DEVICES=0
  • HSA_OVERRIDE_GFX_VERSION tells ROCm the GPU is gfx1151. On ROCm 7.2 it's redundant (the log already says "native") but I keep it as a safeguard, because on older ROCm builds this exact override was mandatory for iGPUs like this one to run at all.
  • PYTORCH_HIP_ALLOC_CONF=expandable_segments:True stops the allocator from fragmenting VRAM on unified memory. Without it you can hit out-of-memory errors with plenty of memory technically free.
  • HIP_VISIBLE_DEVICES=0 pins to the one GPU. Not exciting, but there if you ever add hardware.

One more thing: the server's listen address is hard-pinned to 127.0.0.1 in the launch script — not a config toggle, a hardcoded value. The comment there calls it "the whole security model," which is accurate. Want it reachable from another device? That's your own reverse proxy or VPN, deliberately not a flag you can flip.

How a prompt becomes a picture

People picture this part as mysterious and it isn't. It's a short, fixed pipeline that ComfyUI wires up from its official template:

Z-Image Turbo settings

Z-Image Turbo is the distilled, fast variant of Alibaba's Z-Image model (from what I understand it's out of their Tongyi Lab, roughly 6 billion parameters, Apache-2.0). "Distilled" means something concrete here: 8 steps and CFG 1.0 produce a finished image, instead of the 20–30+ steps older models want. These are the settings from my saved workflow, and they're just the official template defaults. No magic combination to hunt for.

SettingValue
Steps8
CFG1.0
Samplerres_multistep
Schedulersimple
ModelSamplingAuraFlow shift3
Resolution1024×1024
CLIPLoader typelumina2
Negative promptzeroed out (ConditioningZeroOut)

That last row is worth explaining: at CFG 1.0 a negative prompt has nothing to push against, so the workflow zeroes it out with a ConditioningZeroOut node instead of encoding text that does nothing. Type a negative prompt if it makes you feel more in control. It won't change the image.

The three files doing the actual work:

FileSizeRole
z_image_turbo_bf16.safetensors12.3GBdiffusion transformer (bf16)
qwen_3_4b.safetensors8.0GBtext encoder
ae.safetensors0.34GBVAE

Measured performance

These aren't numbers from a release blog post; they're from the journal on this machine. A run of 20 consecutive prompts logged times between 26.62s and 30.41s, so "~27 seconds" is a boring, repeatable average, not a best-case cherry pick. That works out to roughly 2.5–3 seconds per sampling step once you fold in text encoding and VAE decode.

The first image after a cold service start took 43.54 seconds, because that's the run where ~20GB of weights loads off disk. Everything after is warm. If your first image of the day feels sluggish, that's why, not a sign something's wrong.

Running it as a service

I don't want to babysit a Python process in a terminal every time I want an image, so this runs as a systemd user unit, started with the login session:

ExecStart=%h/comfy/start-comfyui.sh
WorkingDirectory=%h/comfy/ComfyUI
EnvironmentFile=-%h/comfy/comfy.env
Restart=on-failure
RestartSec=5
TimeoutStartSec=120

The env file keeps the port and extra launch args in one editable place. On top of that sits a small wrapper, comfyctl, so day-to-day use is:

comfyctl start      # starts the service, waits for it to answer, opens the workflow
comfyctl status     # server health + unit state + newest output file
comfyctl generate "a foggy harbor at dawn, cinematic"
comfyctl stop
comfyctl logs

If the process dies, Restart=on-failure brings it back after 5 seconds, up to 5 times a minute before systemd gives up (so a real crash loop doesn't spin forever). A weekly timer pulls updates with git pull --ff-only, restarts the service, and checks /system_stats before calling it a success. The desktop icon for this thing was generated by the model itself, which I like more than I probably should.

Doing it headless

The web UI is fine for one-offs, but the daily use here is scripted. A stdlib-only Python script builds the graph as JSON, posts it, polls for the result, and prints the path to the finished PNG:

python3 ~/comfy/comfy-generate.py "a foggy harbor at dawn, cinematic" \
  --steps 8 --width 1024 --height 1024 --out ~/Pictures/harbor.png

The HTTP API, the control script, and secure remote access from other devices get a full write-up of their own: Headless ComfyUI: Run It as a Service, Use It from Anywhere.

Gotchas

  • "cuda:0" in the logs is normal. ROCm's PyTorch reports the AMD GPU as a CUDA device. It's not a misconfiguration, and it's not secretly using an NVIDIA card.
  • The first image after a restart is slow. ~43 seconds while weights load, then it settles to ~27. Don't restart mid-session and then panic that something broke.
  • Negative prompts do nothing here. CFG 1.0 zeroes them out by design. If you're debugging a bad image, the negative prompt isn't where the problem is.
  • You can't just open this to your phone. The listen address is hardcoded to 127.0.0.1 on purpose. Remote access means setting up your own reverse proxy or VPN, not editing a config file.
  • It updates itself weekly. Handy until the week it isn't. The fast-forward-only pull stops silent merges, but a breaking upstream change can still land while you weren't watching.
  • 64GB sounds like a lot until you load more. This workflow uses about 20.7GB of weights. Load several large models at once, or run something else GPU-hungry alongside, and the headroom disappears fast.

← More AI & Local LLM