"""Full StableDiffusionPipeline timing with seeded random SD-v1-size components.No checkpoint download or trained-image quality claim. Uses supplied prompt embeddings,1024x1024 output, batch 1, DDIM with 2 steps, guidance_scale=1, and VAE tiling.Choose the Diffusers checkout with PYTHONPATH. Run base/change in alternating freshprocesses; use --save-output on the first pair to compare output tensors exactly."""importargparseimportjsonfrompathlibimportPathimportplatformimportstatisticsimportsubprocessimporttimeimporttorchimportdiffusersfromdiffusersimportAutoencoderKL, DDIMScheduler, StableDiffusionPipeline, UNet2DConditionModelparser=argparse.ArgumentParser()
parser.add_argument("--label", required=True)
parser.add_argument("--dtype", choices=["fp16", "bf16"], default="fp16")
parser.add_argument("--out", type=Path, required=True)
parser.add_argument("--reps", type=int, default=5)
parser.add_argument("--save-output", type=Path)
args=parser.parse_args()
dtype= {"fp16": torch.float16, "bf16": torch.bfloat16}[args.dtype]
torch.backends.cudnn.benchmark=Falsetorch.backends.cudnn.deterministic=Truetorch.manual_seed(0)
vae=AutoencoderKL(
in_channels=3, out_channels=3, down_block_types=("DownEncoderBlock2D",) *4,
up_block_types=("UpDecoderBlock2D",) *4, block_out_channels=(128, 256, 512, 512),
layers_per_block=2, latent_channels=4, norm_num_groups=32, sample_size=512,
).to(device="cuda", dtype=dtype).eval()
vae.enable_tiling()
torch.manual_seed(0)
unet=UNet2DConditionModel(
sample_size=64, in_channels=4, out_channels=4, layers_per_block=2,
block_out_channels=(320, 640, 1280, 1280),
down_block_types=("CrossAttnDownBlock2D",) *3+ ("DownBlock2D",),
up_block_types=("UpBlock2D",) + ("CrossAttnUpBlock2D",) *3,
cross_attention_dim=768, attention_head_dim=8,
).to(device="cuda", dtype=dtype).eval()
scheduler=DDIMScheduler(
beta_start=0.00085, beta_end=0.012, beta_schedule="scaled_linear",
clip_sample=False, set_alpha_to_one=False, steps_offset=1,
)
pipe=StableDiffusionPipeline(
vae=vae, unet=unet, scheduler=scheduler, text_encoder=None, tokenizer=None,
safety_checker=None, feature_extractor=None, requires_safety_checker=False,
)
pipe.set_progress_bar_config(disable=True)
generator=torch.Generator(device="cuda").manual_seed(1234)
embeds=torch.randn((1, 77, 768), generator=generator, device="cuda", dtype=dtype)
latents=torch.randn((1, 4, 128, 128), generator=generator, device="cuda", dtype=dtype)
defrun():
returnpipe(prompt_embeds=embeds, latents=latents, height=1024, width=1024,
num_inference_steps=2, guidance_scale=1.0, output_type="pt").imagesfor_inrange(2):
output=run()
torch.cuda.synchronize()
asserttorch.isfinite(output).all().item()
samples= []
for_inrange(args.reps):
torch.cuda.synchronize()
start=time.perf_counter()
output=run()
torch.cuda.synchronize()
samples.append((time.perf_counter() -start) *1000)
torch.cuda.reset_peak_memory_stats()
output=run()
torch.cuda.synchronize()
peak=torch.cuda.max_memory_allocated() /2**20asserttorch.isfinite(output).all().item()
ifargs.save_output:
torch.save(output.cpu(), args.save_output)
result= {
"label": args.label, "dtype": args.dtype, "pipeline_ms": samples,
"median_ms": statistics.median(samples), "peak_allocated_mib": peak,
"finite": True, "output_shape": list(output.shape), "random_weights": True,
"config": "SD-v1-size UNet and VAE; DDIM 2 steps; guidance 1; supplied embeddings; 1024x1024",
"python": platform.python_version(), "platform": platform.platform(),
"torch": torch.__version__, "cuda": torch.version.cuda,
"diffusers": diffusers.__version__, "diffusers_file": diffusers.__file__,
"gpu": torch.cuda.get_device_name(), "cudnn": torch.backends.cudnn.version(),
"driver": subprocess.check_output(["nvidia-smi", "--query-gpu=driver_version", "--format=csv,noheader"], text=True).strip(),
"attention": "native PyTorch SDPA (default backend selection)",
}
args.out.write_text(json.dumps(result, indent=2) +"\n", encoding="utf-8")
print(json.dumps(result), flush=True)
Withdrawn by the author pending a complete contribution review. The previous readiness verdict was premature: local correctness and random-weight timing results do not establish that this approach and its scope satisfy the project's design and validation expectations. Repository guidance and the full related discussions are being reviewed, and the checklist will record unmet requirements explicitly. No upstream PR has been submitted.
I'd like to coordinate an AI-assisted contribution that vectorizes the row/frame loops used to blend overlapping VAE tiles. This is a proposal for review before opening a PR, following the AI-assisted contribution guidelines.
The prepared implementation is on this branch, at
51ef4e27cd8bb2f818da368af95e56b57eb71da3, based on mainc5469b7ceb606edd7ba6570dcd17d38590a18db6.In complete
StableDiffusionPipelinecalls, the local benchmark's median process latency changed from 1,128.1 to 1,008.9 ms in FP16, and 1,182.6 to 1,017.4 ms in BF16. This uses seeded random SD-v1-size UNet and VAE weights, supplied prompt embeddings, 1024×1024 output, batch 1, DDIM 2 steps, guidance scale 1, native PyTorch SDPA and VAE tiling. It measures the executable pipeline with those settings; it does not establish trained-image quality or performance for longer denoising runs or video models.Environment: Windows 11, Python 3.11.15, PyTorch 2.9.1+cu128, CUDA 12.8, cuDNN 9.10.2, RTX 3070 Ti 8 GB, driver 591.86, Diffusers 0.41.0.dev0. Three alternating fresh-process pairs per dtype, two warmups and five synchronized measurements per process. Paired speedups ranged from 1.052–1.181× for FP16 and 1.128–1.162× for BF16. First-pair outputs matched upstream exactly for both dtypes; peak allocated memory was unchanged at about 2,449.9 MiB.
Proposed scope:
blend_v,blend_handblend_tloops across 18 existing autoencoder implementations with broadcasts over the seam, preserving clamping, in-place output and per-product rounding.autoencoders/vae.py. CUDA coefficients are built on-device, with float64 tensor division to match Python-double rounding and support graph replay. Other devices retain Python-side coefficients, so MPS and other accelerators are not required to support float64.Validation and self-review:
python -m pytest tests/models/autoencoders/test_models_autoencoder_kl.py -k tiling_cuda_graph_replay -q: 6 passed.python -m pytest tests/models/autoencoders -k 'tile_blend_matches_reference_loop or enable_disable_tiling or enable_disable_slicing' -q: 82 passed, 50 skipped on CUDA.DIFFUSERS_TEST_DEVICE=cpu python -m pytest tests/models/autoencoders -k tile_blend_matches_reference_loop -q: 48 passed, 40 skipped.make styleandmake fix-copiesdirectly on Windows with Ruff 0.9.10; all exited 0. Copied code is consistent after normalizing Windows checkout line endings. Setup checks passed.I reviewed similar open and closed work, including #14694, #10488 and the original size-clamping fix #2660. I did not find an existing contribution proposing this same vectorization. The LTX2 diffusion decoder overlap is limited to the existing blend methods and can be rebased if that refactor lands first.
Would maintainers be interested in a single PR with this scope and coefficient approach? I will wait for acknowledgment here before opening it.
Reproducible full-pipeline benchmark
Save the script as
bench_tiled_vae.py. Select each checkout withPYTHONPATH, use the same environment, and repeat base/change then change/base in fresh processes. Repeat with--dtype bf16.