Repository navigation
Add temporal_interleave_upsample_nearest2x: Wan VAE frame interleave + nearest x2 upsample in one pass (triton, eager) - #309
Draft
IvenHsu01 wants to merge 7 commits into
Conversation
temporal_interleave_upsample_nearest2x(x, interleave=False) takes x [B, C, T, H, W], moves the frames into the batch ('b c t h w -> (b t) c h w') and upsamples 2x with nearest-exact, returning the contiguous [B * T, C, 2H, 2W] input of the Conv2d that follows: the upsample body of the Wan VAE Resample (upsample2d / upsample3d). With interleave, x is the [B, 2C, T, H, W] time_conv output and the frames of its two channel halves are interleaved first, as the upsample3d reshape / stack / reshape does. Public wrapper, torch.ops.comfy_kitchen.temporal_interleave_upsample_nearest2x custom op with a fake impl, and the eager backend as the reference.
Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
One gather kernel writes the contiguous [N, C, 2H, 2W] output straight from x, so the stack, the rearranged copy and the upsample of the eager path, which each read and write the full tensor, become one read of x and one write. A program row loads block_r source rows of x through x's strides, duplicates every pixel along the row with tl.interleave and stores the result to both output rows; for a scale of 2, nearest-exact maps an output index d to d // 2, so the output is a bit-identical copy. The tiles are autotuned over 7 (block_r, block_ws) shapes x 4 / 8 warps. The Triton backend takes fp32 / fp16 / bf16 5D x on cuda devices; the call rule declines empty inputs, interleave with an odd channel count, and the plain form (interleave=False) below 12M output elements, where the single eager upsample kernel was faster (crossover between 9.58M and 14.4M output elements on RTX 5090 and Radeon 8060S). Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
…upported_inputs_go_to_eager The eager backend also limits x to fp32 / fp16 / bf16, so for an fp64 input no backend is capable and get_capable_backend raises NoCapableBackendError. Check that triton declines fp64, and keep the CPU input routed to eager. Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: true
|
Format the lines this branch adds (new files in full; only the added ranges in files that are not format-clean on main). Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
…mments Comment-only change; the speedups and timings stay in the PR description. Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
…all-rule message and test comments Message and comment change only. Signed-off-by: ChanFu, Hsu <ChanFu.Hsu@amd.com>
This branch has not been deployed
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.
Adds
ck.temporal_interleave_upsample_nearest2x(x, interleave=False), which takes a[B, C, T, H, W]tensor, moves the frames into the batch ('b c t h w -> (b t) c h w') and upsamples it 2x withnearest-exact, returning the contiguous[B * T, C, 2H, 2W]input of the Conv2d that follows. Withinterleave=True, x is the[B, 2C, T, H, W]output of the temporal conv and the frames of its two channel halves are interleaved first ([B, C, 2T, H, W], frame2t + kfrom halfk). This is the upsample body of the Wan VAEResample(comfy/ldm/wan/vae.pyandcomfy/ldm/wan/vae2_2.py,Resample.forward, modesupsample3dandupsample2d): thereshape/torch.stack/reshapeframe interleave aftertime_conv, therearrangeto(b t) c h wandnn.Upsample(scale_factor=(2., 2.), mode='nearest-exact')before the Conv2d inself.resample. In ComfyUI's current path the interleave form runs as four kernels that each read and write the full activation (three copy kernels for the stack and the rearranged view, then the upsample), and the plain form with more than one frame copies the rearranged view before the upsample; comfy-kitchen has no upsample or interleave op.F.interpolate(..., scale_factor=(2., 2.), mode="nearest-exact")), made contiguous.tl.interleaveand stores it to both output rows. For a scale of 2, nearest-exact maps an output indexdtod // 2, so the output is a copy of input pixels, bit-identical to eager. fp32 / fp16 / bf16 x on cuda devices (CUDA and ROCm); any strides. The tile shape is autotuned over 7(block_r, block_ws)shapes with 4 / 8 warps. The call rule declines empty inputs and, for the plain form (interleave=False), outputs below 12M elements, where the single eager upsample kernel was faster than a direct launch of the kernel (crossover between 9.58M and 14.4M output elements on the RTX 5090 and the Radeon 8060S); those calls run eager.Speedup over ComfyUI's current path (reshape / stack / reshape + rearrange +
nn.Upsamplenearest-exact), bf16, per call of the public op at the input shapes captured from real Wan VAE decodes. Each arm runs in a fresh process, ABAB with 2 pairs (20 warmup calls, then 5 loops of 100 back-to-back calls with a synchronize around each loop, median per call), so the CPU launch and dispatch cost of each call counts. Times are pair 1; the speedups are pair 1, pair 2. Every output istorch.equalto the current path, and every call was served by the backend the call rule picks (eager for the first row, triton for the rest):On the RTX 5090 the kitchen time of the (1, 2048, 1, 44, 80) interleave shape was 49.6 us in pair 1 and 33.0 us in pair 2. Two plain-form shapes are slower than the current path through the public op. The (1, 384, 1, 60, 104) shape runs eager by design, but the eager fallback pays the op's dispatch cost too (on both GPUs). The (1, 1024, 1, 44, 80) shape (14.42M output elements) is above the 12M threshold, so triton serves it: 1.29x / 1.36x on the Radeon 8060S, but 0.67x / 0.68x on the RTX 5090. The threshold is shared by both GPUs and is not changed in this PR.
Environment: RTX 5090 on Windows (torch 2.14.1+cu130, CUDA 13.0, triton-windows 3.9.0, Python 3.12); Radeon 8060S (RDNA3.5) on Windows (ROCm torch 2.15.0a0+rocm10.1.0a20260907, triton-windows 3.8.0, Python 3.12). Tests and benchmarks on 4f24e06 on both GPUs (54673ea and the head 668b547 after it only edit comments and the text of one call-rule message):
test_temporal_interleave_upsample_nearest2x.py64,test_backends.py12,test_constraints.py42 passed on the RTX 5090 with the CUDA extension from the 0.2.41 wheel; the same on the Radeon 8060S with the HIP extension only, excepttest_constraints.py40 passed / 2 skipped (CUDA-only).Not covered yet: end to end in ComfyUI (not run on either GPU); Linux; fp16 / fp32 timing (the benchmark is bf16 only). Interleave inputs smaller than the Wan decode shapes (smallest measured output 28.8M elements) are served by triton without a size limit but were not timed; the 12M routing threshold was measured in bf16 only. The single-image path of the Wan2.2 VAE (
feat_cacheNone) runs the upsample and the Conv2d together in row strips (strip_apply) and is not a call site of this op. ComfyUI integration (Wan VAE) is a separate PR; ComfyUI keeps comfy-kitchen's triton backend off unless the server is started with--enable-triton-backend.