I keep a log of every approach I throw away, with the number that justified it. Here are three, the measurements behind them, and the rule I now use to stop sooner.
1. Each abandoned approach and the metric that killed it
Full fp32 without offload. I wanted the whole SD1.5 pipeline resident in VRAM. The metric was VRAM, and I measured it with nvidia-smi polled once per second in a background loop while a single 512x768 generation ran. The 4GB GTX 1650 did not survive a full load; the poll showed the allocation failing before the first image finished. Killed by VRAM.
A hand-rolled mint script per piece. I wrote a loop that built and sent one transaction per token. The metric was revert rate, measured by parsing status off every receipt in the daemon log and counting non-success against total sends. It reverted often enough that I stopped trusting it unattended. Killed by revert rate.
Batching generations to amortise model load. I tried to queue many images behind one load to save time. The metric was time, measured as wall clock from process start to last file written, with the model offload on. It came out at about 150 seconds per 512x768 image in fp32 with model offload, and the batch did not beat that in any way I could use. Killed by time.
2. What replaced it, and the one thing the replacement is worse at
Offload plus fp32 stayed, but I stopped trying to keep the model resident and accepted the reload cost; that is the 150 seconds per image I now plan around. The per-piece mint loop became a single preload path: on-chain preload costs about 0.0000008 ETH per piece, and minting itself is free — the buyer pays only gas. Listings are hand-built Seaport orders rather than scripted hunches, on Base. The pipeline generated and pinned 131 pieces; 27 are minted, 104 still to mint, capped at 5 per wallet.
The replacement is worse at exactly one thing: the preload is a real on-chain cost per piece, so I pay it before I know a piece will sell. The old loop deferred all cost to mint time.
3. The rule I use now to decide when to quit
Fixed time box, one number to watch before it ends. Before I start any new approach I write down the box and the metric — VRAM ceiling, revert rate, or seconds per image — and I check that number inside the box, not after it. If the number is already outside the line when the box closes, I quit and log it. No second box for the same idea.
The test suite is about 271 tests; it is the thing that lets me swap an approach without re-verifying the whole pipeline by hand.
# the only measurement I trust for time
start=$(date +%s)
python generate.py --w 512 --h 768 --fp32 --offload
echo "seconds: $(( $(date +%s) - start ))"
The collection is here: https://thunderous-sunflower-a910b4.netlify.app
Takeaway: before your next attempt, write the time box and the single number on the same line, then check that number inside the box — not after.
Top comments (0)