DistVAE updates including tile-parallel VAE execution - #750
Merged
Conversation
…ty rewrites ModelCapabilities is frozen, so re-declaring the whole block without a flag reads as False rather than leaving it alone. Wan2.2 distilled I2V, Qwen-Image and Z-Image-Turbo each lost enable_tiling and enable_slicing that way, which silently refused --enable_tiling on three models that support it.
CausalWan sets use_fp8_gemms=False in the same class body that lists fp8_gemm_module_list=["transformer.blocks"], so --use_fp8_gemms quantizes the transformer blocks today. The declaration is what is wrong: nothing else in the model refuses FP8, and the capability check that would have caught the contradiction never ran for boolean flags.
The capability loop tested every int-valued config with value > 1, written for degrees like ulysses_degree=4. bool subclasses int, so True took that branch, True > 1 is False, and no boolean capability was ever refused: --use_parallel_vae on a model that cannot do it ran as a silent no-op rather than an error, and the same held for every other boolean flag. Booleans now take the branch already written for them. The declarations this makes load-bearing were audited against the code that reads them: every model declares the VAE flags, use_vae_channels_last_format defaults true, the quantization flags agree with each model's gemm module lists after the CausalWan fix, and both hybrid schedule flags are declared exactly where _calculate_hybrid_attention_step_multiplier accounts for the model's steps.
One of the two definitions described tiling, a tile at a time, which is what --enable_tiling does. Slicing decodes one batch item at a time and does nothing at batch size 1.
…not honour Diffusers hands every autoencoder enable_tiling and enable_slicing through a shared mixin whether or not the class implements them, so calling one on a VAE too old to tile did nothing and reported nothing. Both features also arrived class by class over several releases, Wan's tiling in 0.34, one past the diffusers floor setup.py asks for, so an install that satisfies the floor can still be short of the class the model loads. Probing the state flag the mixin itself checks, rather than the method, answers whether the installed release can really do it. That knowledge lives in a new xfuser/core/utils/vae_tiling.py so nothing about diffusers VAE internals accumulates in the runner.
… through A staged model loads a second pipeline with its own VAE, and the later stage is the one decoding at full resolution. --enable_tiling only reached self.pipe.vae, so LTX-2 carried its own _enable_options override to pass the flags along to the second stage, and LTX-2.3's override handled slicing only. Collecting the VAEs in the base class covers both stages for every staged model, including ones added later, and both overrides come out. The alternative, a hook each subclass overrides, fails silently: a subclass that forgets gets no error, only a flag that misses the largest decode.
A VAE's default tile window tracks its training resolution and never shrinks, so decoding above that resolution can run out of memory with tiling already on: the tile itself is too large. The window was only reachable by setting diffusers attributes by hand, and which attributes depends on the VAE class. --vae_tile_size takes one pixel-space edge and rescales whichever attributes the class carries, covering all four families diffusers ships: the legacy latent/sample pair, the stride form, per-axis overlap factors, and overlap-only. Sizes the attributes cannot express exactly snap down to the nearest workable window rather than rounding into a fractional latent size the decoder would fail on, and a size above the VAE's own window is declined, since widening it would raise peak memory. The flag turns tiling on by itself. LTX-2.3 tiles its stage-2 VAE at load, so requiring --enable_tiling alongside would mean tiling every stage to reach the one that ran out of memory. The arithmetic and the diffusers attribute knowledge live in vae_tiling, tested against every VAE class the runner models load.
A VAE decode that ran out of memory reported only torch's allocation figures, from a stage most of the memory-saving flags do not name, so the next step was not obvious. The guard adds the applicable one: tiling where the VAE is not tiling yet, otherwise a concrete --vae_tile_size below the current window, chosen through the same snapping the flag itself uses so the suggestion cannot be refused on the next run. It reads the VAE's own state rather than the config flags, since a model can arrive already tiling with no flag set. A narrowed window can also leave a tile thinner than a convolution's padding, which torch reports from deep inside the decoder without mentioning tiles. That message is kept and prefaced with the window that caused it. Only failures matching that padding signature are reattributed, and only when this run narrowed the window, so a dtype or device error still surfaces as itself.
Five runner files each carried their own module-level _setup_parallel_vae, differing only in what the VAE they were written for needed. A sixth model wanting parallel VAE meant copying a fifth wiring, and knowing which of DistVAE's adapters its decoder blocks call for by reading someone else's. The VAE answers that itself: its decoder blocks say which adapter fits, and refusing up front replaces an assertion thrown from inside a half-built replacement decoder with an error naming the flag and pointing at --vae_tile_size. So the base class can do the whole job, and every call site becomes the same three lines. What looked model-specific was a function of the VAE's config. Both quirks come from patch_size: the encoder adapter shards by the encoder's own downsampling, so a patching VAE has to divide that factor out, and the decoder adapter's patchify assumes no patching because Wan does none. Deriving both reproduces every value the five copies passed, Cosmos 3's 16 over 2 included, and is a no-op for VAEs that do not patch. A missing DistVAE adapter now raises instead of logging and running single-rank. Asking for a sharded encoder and silently getting only a sharded decoder is the kind of quiet no-op this branch removes elsewhere.
…e VAE Z-Image, Z-Image-Turbo and SD3.5 decode through AutoencoderKL variants built from the 2D blocks DecoderAdapter was written against, and CausalWan and Wan2.1-VACE through Wan's blocks, so all five can shard a decode they were quietly ignoring the flag for. Nine models still cannot: Qwen-Image and Krea-2, the HunyuanVideo family and LTX-2, each of whose decoders is built from blocks DistVAE has no adapter for. They fail naming the missing adapter and pointing at --vae_tile_size, which lowers the same memory without a second GPU.
Sharing the decoder wiring meant Cosmos 3's patch_size read now runs for every VAE, and patch_size does not mean the same thing in every VAE. Flux 2 declares (2, 2) for the pixel unshuffle at its boundary, so `patch_size > 1` raised TypeError comparing a tuple to an int, and --use_parallel_vae broke on Flux 2 and Ideogram 4, which wrapped their decoders without reading any config before. Anything other than a single number now reads as no patching, which is what it is to an adapter. The tests only asked which adapter fits each VAE class, never wrapped with it, because the real adapters need a process group. Standing one in covers the wrapping too, so every VAE class a runner loads is now put through the config reads that wrapping does, Flux 2's patch_size included.
…w fits DistVAE has adapters for the QwenImage, HunyuanVideo, HunyuanVideo 1.5 and LTX-2 decoders, so Qwen-Image, Qwen-Image-Edit, Krea-2-Raw, Krea-2-Turbo, HunyuanVideo, HunyuanVideo 1.5 and its distilled and sparse variants, LTX-2 and LTX-2.3 can shard a decode they were being refused. That is every VAE class a runner model loads, which is what the expectations here now say. Picking an adapter was a special case for Wan wrapped around the 2D one; the four new families would have made four more of it, so the block types each family's decoder is built from move into a table. Their names are read off the installed diffusers rather than imported, the way Wan's already were, so a VAE newer than the install matches nothing instead of breaking the choice for every other VAE. The one shape DistVAE cannot take is an LTX-2 decoder with inject_noise on, where each rank would draw noise for its own rows and the ranks together would not reconstruct what one draws. It is refused here rather than by the adapter, which discovers it partway through replacing a decoder and would leave the VAE half sharded. No released LTX-2 checkpoint enables it. Co-authored-by: Cursor <cursoragent@cursor.com>
parallelize_encoder read the decoder to decide what the encoder was, which worked only while DistVAE had a single encoder adapter and the decoder was still recognisable. The runner shards the decoder first, and that replaces its up blocks with adapters, so by the time the encoder is asked for the decoder answers to nothing and every model declaring the flag was refused. DistVAE now has an encoder adapter for all seven families, so the table gains a column for them and each half is recognised by its own blocks, which is the only way either can be read after the other is sharded. Wan needs two shapes in that column: 2.2 groups each encoder stage into a WanResidualDownBlock, while 2.1 lays the same residual blocks, attentions and resamples out flat. A 2D encoder is matched on DownEncoderBlock2D as before, and its ratio is counted off the stages that downsample rather than defaulting to 8, because these VAEs record no ratio anywhere and the adapter cuts bands by it: a three-stage checkpoint narrows by 4 and would otherwise be cut for 8. Co-authored-by: Cursor <cursoragent@cursor.com>
…code Thirteen models VAE-encode something before they generate, and every one of them was paying for that on a single rank while its decode was sharded. Ten classes declare it here; Flux.2-Klein-4B, HunyuanVideo-1.5-Distilled and LingBot-Video-Dense inherit the block from a parent that does. What is encoded, and how large, differs by model. LingBot's refiner is the extreme: it encodes the whole base video at the final output resolution, up to 1080p, which is the largest encode of the set. Wan2.1-VACE is next, encoding a full-length conditioning video twice over, once for each half of the mask, plus a pass per reference image. Flux-Kontext, Qwen-Image-Edit and FLUX.2 encode a single image at generation size, and HunyuanVideo 1.5 and CausalWan a single frame, where the win is smaller but the adapter is free. Five of the ten only encode on some runs. Wan2.2-TI2V and HunyuanVideo 1.5 load a pipeline that encodes for --task i2v and one that does not for t2v; FLUX.2, Klein and CausalWan encode the reference images they are given and nothing when given none. A sharded encoder that never runs costs nothing, so the flag is declared once rather than per task. Sizing is the one thing this relies on: the adapter cuts an image into bands that are whole multiples of the VAE's ratio, and each of these pipelines already holds what it encodes to a multiple of that ratio, at the size it is about to generate at. Co-authored-by: Cursor <cursoragent@cursor.com>
Every decoder call costs the same whatever the tile it is given, and under --use_parallel_vae that cost is a round of collectives rather than arithmetic: a Patchify, a halo exchange per convolution, a reduction per norm, and a DePatchify to gather the result. Measured on FLUX.2-Klein-4B at 4 GPU it is ~26 ms, flat from 121 tiles to 1849. Narrowing the window to fit a decode in memory therefore multiplies a fixed cost, which is what leaves a 64px window an order of magnitude slower than the VAE's own. Tiles are independent and, away from the edges the latent bounds clip, all the same shape, so they can be stacked on the batch dimension and share that round. The budget is an area rather than a count, since activation memory follows the area being decoded and one count would batch the widest tiles into an allocation the VAE was never sized for. The area used is the VAE's own tile, read before --vae_tile_size can narrow it, so a run that did not ask for a smaller tile decodes exactly as it did and a run that did stops paying for its size twice. Nothing to set, and no new flag. Scoped to the VAEs that tile by overlap fraction, AutoencoderKL and AutoencoderKLFlux2. Wan, Qwen-Image and the video VAEs walk a stride they store outright over a loop with its own blending, and keep their own tiled_decode.
…ds it Reverting AITER's swap of torch.nn.GroupNorm sat in the branch that validates --use_parallel_vae, next to the check that DistVAE is installed, where it read as one more thing the flag disallows. It is not: it is a condition the sharding itself has, and the reason is entirely about how the adapters find their norms. Moving it next to the isinstance check it protects puts the reason where the next person to touch that check will see it. Behaviour is unchanged. The three tests are new; nothing exercised this before, including the failure it exists for, which is a VAE reading as unshardable because its norms are not the class the check asks about.
…om it Qwen-Image sizes its causal feature cache by counting its causal convolutions on every call, asking isinstance against its own class. Sharding replaces all of them, so the count came to zero, the list was empty, and the first convolution to want its entry indexed off the end: an IndexError from inside diffusers on the first decode. Counting before either half is replaced and holding the answer is what the VAE would have done had it cached the count, as Wan does.
test_sharding.py imported shard_transformer_blocks, which exists neither here nor on upstream main - it became shard_component, taking a list of attributes to wrap rather than one attribute name. The import error failed collection for the whole of tests/core, so no xDiT test could be run by directory. The invalid-attr case now expects the AttributeError rgetattr raises rather than the ValueError the older function checked for.
A ROCm install has neither, and an import error at module scope stops the whole of tests/core collecting rather than just these two.
test_vae_parallel takes its VAE configs from test_vae_tiling rather than repeating them, which needs the repo root on sys.path and tests to be the one here. Some installs carry an unrelated top-level tests package, and a namespace directory loses to an installed package wherever it sits on the path, so this takes the __init__.py that makes it a real one as well.
On ROCm, importing xfuser swaps torch.nn.GroupNorm for AITER's, so these built VAEs whose norms DistVAE will not shard, and decoding one on the CPU reaches a kernel that only exists on the GPU. Production reverts before building a VAE it means to shard; a session fixture does the same for the tests, and the revert tests name the class they expect rather than whichever was left behind.
…rest do The Ideogram 4 and LingBot Video runners pulled their transformer wrapper in at module scope, so importing the registry paid for both. tests/core/test_compat has been asking for this since it landed.
It reads torch.version.cuda and torch.version.hip, never torch.cuda.is_available, so patching availability only ever agreed with the machine it ran on: a ROCm build answers to HIP and reported cuda where the test asked for cpu.
The two mask tests asked for a strictly diagonal answer from a 2x2x2 cube, in which every point is within one step of every other and every block therefore neighbours every block. They now run along a row, where a block touches itself and the two beside it, and the cube keeps its own test saying what it is.
Measured on FLUX.2-Klein-4B at 2048x2048 over 4 GPUs: peak VRAM is 21.9 GB untiled and 15.9 GB at the VAE's own window, then flat - 15.5 at 512px, 15.7 at 256 and 128, and back up to 16.4 at 64 as per-tile bookkeeping outweighs the smaller working set. Over that same range the share of pixels more than 10% off the untiled decode goes 1.5%, 3.9%, 11.0%, 13.6%, 14.6%, since each tile is normalized over its own content and the blend that hides the seams is a fixed fraction of a shrinking window. Neither sharding nor tile batching contributes: plain tiling, tiling with --use_parallel_vae, and both with batching agree to within 0.05 points at every window. So the knob is not one to keep turning. Once the VAE is no longer what peaks, shrinking it cannot lower the peak, and everything past that point is image quality spent for nothing. Both help strings and the OOM hint now say to step once and compare peak VRAM. No behaviour change.
The batch budget was the VAE's own tile area, held constant however narrow the window got. That made every decoder call carry the same area as the default window, which is the whole of what --vae_tile_size is asked to reduce: measured on Klein-4B at 2048x2048, a 64px window peaked at 16354 MB batched against 15106 MB unbatched, and 16213 MB at the default window. Someone narrowing the window to fit a decode was spending more memory than if they had left the flag alone, and taking the image degradation of a small tile for it. Budget by the geometric mean of the VAE's own tile area and the narrowed one instead. Halving the window's area now halves the area a call carries and doubles the tiles sharing each round of collectives, so both of the things the knob is reached for keep improving as it shrinks. At the VAE's own window the two areas are equal, the budget is one tile, and the decode is bit-identical to upstream as before. It is a trade, not a free win: a 64px window batches 16 tiles a call rather than 256, so its collective count rises with it. That is the right end to give ground on, since a window that small degrades the image badly enough that no one should be sitting at one for long.
The rule in 9feba6d is right but its explanation was written in tile areas, which is not what anyone sets, and the commit message got the scaling wrong as a result. The budget is the geometric mean of the two areas, which is the product of the two edges, so it is linear in the edge --vae_tile_size names: halve the number and the area a decoder call carries halves. Equivalently, a batched decode at window W costs what an unbatched decode at the geometric mean of W and the VAE's own window costs. Same arithmetic, no behaviour change. The test now asserts the linear-in-edge property directly rather than a table of areas that happened to satisfy it.
…shard each one Tiling and --use_parallel_vae divide the same decode, and composing them divided it twice. DistVAE shards the rows of whatever it is handed and a tiled decode hands it one tile at a time, so a Patchify, a halo exchange per convolution, a reduction per norm and a gather were paid per tile rather than per decode. On a Wan decode at 768x768x49f the collectives came to exactly sixteen times the untiled count, one multiple per tile, and four ranks decoded no faster than one: each rank's share of the arithmetic shrank while its share of the exchanges did not. Tiles are independent, which the rows inside a tile are not. Where the tiling loop is one xFuser owns, the decoder is now left as it is and whole tiles go out to the ranks instead, which costs two exchanges for the whole decode however many tiles there are. A tile narrower than the group also stops being a refusal, since nothing divides a tile any more.
Wan and Qwen-Image walk a stride they store, over a loop of their own with a frame axis and a feature cache, so the batched decode left them alone and their tiles were the ones paying the per-tile collective bill most heavily: sixteen tiles at 768x768x49f, sixteen times the exchanges, and four ranks no faster than one. The cache is threaded through the frames of a tile and cleared where each tile starts, so a tile is independent of every other tile in the way its frames are not, and the loop is reimplemented here only to hand those tiles round a group. Without a group to hand them to the VAE keeps its own loop, since there would be nothing to gain from a second author. The two classes are recognised by name, because nothing about a VAE's attributes says which loop body it has: Hunyuan, LTX-2 and CogVideoX carry the same stride attributes and the same cache and walk them differently. The dispatcher test asked for a batched decode to be bit-exact, which batching never was: a convolution blocks off the rows it is handed. Held to the same 1e-4 as the batching tests it sits beside, which a misplaced tile would still miss by order one.
The stand-in asked for patch_size on its own, which leaves the decoder ending on three channels where unpatchify wants twelve, and diffusers' own tiled_decode raised before the reimplemented one was reached. Wan 2.2 carries the patch in its channels and in its spatial ratio as well as in the flag, so the stand-in now does too.
Keep height and width as the sole explicit tile-window controls so runner behavior has one unambiguous shape contract. Co-authored-by: Cursor <cursoragent@cursor.com>
…vae-tile-batching Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # tests/core/test_vae_parallel.py # tests/core/test_vae_tile_parallel.py # tests/core/test_vae_tiling.py # xfuser/core/utils/vae_parallel.py # xfuser/core/utils/vae_tile_parallel.py # xfuser/core/utils/vae_tiling.py # xfuser/model_executor/models/runner_models/base_model.py
Co-authored-by: Cursor <cursoragent@cursor.com>
Use exact rectangular windows and absolute per-axis overlap while validating the DistVAE version and API contract at startup. BREAKING CHANGE: replace --vae_tile_overlap with paired height and width pixel flags and require DistVAE 0.0.0beta9. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # xfuser/model_executor/models/runner_models/ltx.py # xfuser/model_executor/models/runner_models/wan.py
Accept both coordinated and dedicated process groups during decoder parallelization, and keep rectangular tile guidance focused on the sharded axis. Co-authored-by: Cursor <cursoragent@cursor.com>
Validate the canonical DistVAE API and route LTX stage tiling through the shared VAE manager so runtime flags control every stage. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Run DistVAE setup once after post-load initialization so staged pipelines share the same ordering. Remove runner-specific forwarding and brittle source-structure tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Rely on the declared DistVAE version floor and direct public imports instead of duplicating its API contract. Keep behavioral coverage while removing compatibility archaeology and redundant integration tests. Co-authored-by: Cursor <cursoragent@cursor.com>
Keep runner capability declarations concise where nearby comments only restate pipeline behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
Exercise DistVAE's real latent-row semantics so narrow valid tiles cannot be rejected behind a mocked boundary. Co-authored-by: Cursor <cursoragent@cursor.com>
Preserve dedicated raw groups and use the configured VAE subgroup for in-process decoding instead of falling back to the world group. Co-authored-by: Cursor <cursoragent@cursor.com>
Turn decoder split failures into shape-aware guidance that suggests complete-tile parallelism when the VAE supports it. Co-authored-by: Cursor <cursoragent@cursor.com>
avjves
reviewed
Aug 17, 2026
avjves
left a comment
Collaborator
There was a problem hiding this comment.
Thanks for this! It really clear things up as well as adds bunch of new features :)
Left a couple of comments still.
avjves
reviewed
Aug 17, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
Author
|
@avjves - the associated DistVAE release has been published. |
Collaborator
|
LTX-2.5 support was merged. Can you still add the changes to that model card? :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When VAE tiling and
--use_parallel_vaeare active on a supported VAE, DistVAE assigns complete tiles to ranks and assembles the decoded output afterward. Without tile distribution, the decoder is sharded along its latent-height axis.VAE tiling primarily reduces peak memory. Complete-tile distribution can also reduce decode latency when the tile grid supplies enough balanced work.
Tiling also has a nice side effect of shorter compile times.
Some illustrative benchmark examples are provided below.
Execution modes
--use_parallel_vae--enable_tilingModels declaring
use_parallel_vae_encoder=Truealso receive a row-sharded encoder. Complete-tile distribution applies only to decoding.Row sharding splits one latent along its height axis. It can reject shapes that do not align with the VAE's patch or downsampling unit, leave too few bands for the selected rank count, or cannot provide the required convolution halo. Complete-tile distribution avoids those intra-tile split constraints and can therefore use configurations that row sharding rejects.
Included
VAEManagerto configure every unique VAE used by single-stage and multi-stage pipelines.--vae_tile_size_height--vae_tile_size_width--vae_tile_overlap_height--vae_tile_overlap_widthGroupCoordinatorgroups and dedicated rawProcessGroupinstances.Dependency
Depends on the companion DistVAE beta9 change. xdit-project/DistVAE#14
DistVAE beta9 must be published before this PR merges. The latest version currently available from PyPI is beta5, while
setup.pyrequiresdistvae>=0.0.0beta9.Benchmark results
gfx1201
End-to-end latency and peak VRAM by VAE decode path.
gfx1201 (AMD Radeon AI Pro R9700S, 32 GiB/card).
192x1024 ov 64x0128x1024 ov 32x0384x2048 ov 128x0192x2048 ov 64x0192x1024 ov 64x0384x1024 ov 128x0384x2048 ov 128x0192x2048 ov 64x0384x1152 ov 96x0192x1152 ov 48x0Wan2.2-TI2V-5B Tiled
Row Sharded
row-wan.81f.4g.row.mp4
Tiled
tiled-wan.81f.4g.fine.mp4
Qwen-Image-2512 2K
FLUX.2-klein-4B 1k
Held fixed across every run:
attention_backend=aiter_flydsl_fp8,ring_degree=1,seed=42,use_fp8_gemms=true,use_torch_compile=true,warmup_calls=1.ulysses_degreeis set to the GPU count, 2 or 4.fully_shard_degreeis set to the GPU count, 2 or 4 (Qwen-Image-2512 only).FLUX.2-klein-4B only:
guidance_scale=1.0,num_iterations=2,prompt=A ginger kitten.Qwen-Image-2512 only:
guidance_scale=0.0,memory_efficient_sharding=true,num_iterations=1.Wan2.2-TI2V-5B only:
flow_shift=5,guidance_scale=5.0,task=i2v,input_images=/app/data/wan_input.jpg,num_iterations=1.gfx950
End-to-end latency by VAE decode path.
gfx950 (AMD Instinct MI355X, 287.98 GiB/card),
128x2048 ov 32x0128x2048 ov 32x0192x2048 ov 64x0native window192x832 ov 48x0736x224 ov 0x64256x256 ov 64x64HunyuanVideo-1.5-720p
Row Sharded
hunyuan_video_1_5_u8r1_tc_True_720x1280_t2v_0.-.row.mp4
Tiled
hunyuan_video_1_5_u8r1_tc_True_720x1280_t2v_0.mp4
Held fixed across every run:
attention_backend=aiter,ulysses_degree=8,ring_degree=1,use_torch_compile=true,use_fp8_gemms=false,num_iterations=1,warmup_calls=1. Everythingelse is that model's CI config unchanged, and the per-model settings that differ are:
FLUX.1-dev —
seed=0,guidance_scale=0.0,max_sequence_length=256.FLUX.2-dev —
seed=42,guidance_scale=4.0,max_sequence_length=512.Qwen-Image-2512 —
seed=42,guidance_scale=0.0.LTX-2.3 —
seed=42,guidance_scale=3.0; the pipeline fills in its own frame count, 121.Wan2.2-I2V-A14B —
seed=42,input_images=/app/data/wan_input.jpg,num_frames=81; it isimage-to-video and resizes its canvas to the input, so it decodes 1104×832 rather than the
720×1280 in the config.
HunyuanVideo —
seed=1168860793,guidance_scale=6.0,batch_size=1.HunyuanVideo-1.5-720p —
seed=1168860793,task=t2v.Additional fixes
Test maintenance
flash-attnpackage is unavailable.shard_componentAPI.