Spaces:
Running on Zero
Running on Zero
| # Copied and adapted from LightX2V's Wan Triton scale-shift kernel. | |
| import torch | |
| import triton # type: ignore | |
| import triton.language as tl # type: ignore | |
| def _fused_scale_shift_4d_kernel( | |
| output_ptr, | |
| normalized_ptr, | |
| scale_ptr, | |
| shift_ptr, | |
| rows, | |
| inner_dim, | |
| seq_len, | |
| num_frames, | |
| frame_seqlen, | |
| BLOCK_N: tl.constexpr, | |
| ): | |
| pid_row = tl.program_id(0) | |
| pid_col = tl.program_id(1) | |
| col_offsets = pid_col * BLOCK_N + tl.arange(0, BLOCK_N) | |
| mask = col_offsets < inner_dim | |
| row_base = pid_row * inner_dim | |
| norm_ptrs = normalized_ptr + row_base + col_offsets | |
| out_ptrs = output_ptr + row_base + col_offsets | |
| b_idx = pid_row // seq_len | |
| t_idx = pid_row % seq_len | |
| frame_idx_in_batch = t_idx // frame_seqlen | |
| scale_row_idx = b_idx * num_frames + frame_idx_in_batch | |
| scale_ptrs = scale_ptr + scale_row_idx * inner_dim + col_offsets | |
| shift_ptrs = shift_ptr + scale_row_idx * inner_dim + col_offsets | |
| normalized = tl.load(norm_ptrs, mask=mask, other=0.0) | |
| scale = tl.load(scale_ptrs, mask=mask, other=0.0) | |
| shift = tl.load(shift_ptrs, mask=mask, other=0.0) | |
| one = tl.full([BLOCK_N], 1.0, dtype=scale.dtype) | |
| output = normalized * (one + scale) + shift | |
| tl.store(out_ptrs, output, mask=mask) | |
| def fuse_scale_shift_kernel( | |
| x: torch.Tensor, | |
| scale: torch.Tensor, | |
| shift: torch.Tensor, | |
| ): | |
| if not x.is_contiguous(): | |
| x = x.contiguous() | |
| assert x.dim() == 3, "x must be [B, L, C]" | |
| assert scale.dim() == 4 and shift.dim() == 4, "scale/shift must be [B, F, 1, C]" | |
| assert scale.shape == shift.shape, "scale and shift must have the same shape" | |
| assert scale.shape[0] == x.shape[0] and scale.shape[2] == 1 and scale.shape[3] == x.shape[2], \ | |
| "scale/shift must match x as [B, F, 1, C]" | |
| B, L, C = x.shape | |
| output = torch.empty_like(x) | |
| rows = B * L | |
| x_2d = x.view(rows, C) | |
| output_2d = output.view(rows, C) | |
| grid = lambda META: (rows, triton.cdiv(C, META["BLOCK_N"])) # noqa | |
| num_frames = scale.shape[1] | |
| assert L % num_frames == 0, "seq_len must be divisible by num_frames for scale/shift" | |
| frame_seqlen = L // num_frames | |
| scale_reshaped = scale.squeeze(2).reshape(-1, C).contiguous() | |
| shift_reshaped = shift.squeeze(2).reshape(-1, C).contiguous() | |
| _fused_scale_shift_4d_kernel[grid]( | |
| output_2d, | |
| x_2d, | |
| scale_reshaped, | |
| shift_reshaped, | |
| rows, | |
| C, | |
| L, | |
| num_frames, | |
| frame_seqlen, | |
| ) | |
| return output | |