Download code/tt_diffrhythm/common.py from sunandbean/diffrhythm-1.2-p100a: direct link, hf CLI and curl.
- Browser
- Download file 4.34 kB
-
https://huggingface.co/sunandbean/diffrhythm-1.2-p100a/resolve/main/code/tt_diffrhythm/common.py
- Command line
-
hf download hf://sunandbean/diffrhythm-1.2-p100a/code/tt_diffrhythm/common.py
-
curl -L -o common.py https://huggingface.co/sunandbean/diffrhythm-1.2-p100a/resolve/main/code/tt_diffrhythm/common.py
4.34 kB
| # SPDX-License-Identifier: Apache-2.0 | |
| """Device and host helpers shared with the ACE-Step port. | |
| Extracted verbatim from `tt-acestep` (Apache-2.0), where the same code opens the card, reports | |
| DRAM, moves tensors, and prepares checkpoint tensors for ttnn: the matmul layout, the | |
| adjacent-pair head permutation ttnn's rotary kernel expects, and the tiled rotation matrix. | |
| The two ports also share `worker.py`, `remote.py`, `wire.py` and `oobleck_vae.py`; this module | |
| exists so that this repository stands alone. | |
| """ | |
| from __future__ import annotations | |
| from dataclasses import dataclass | |
| import torch | |
| import ttnn | |
| MEM = ttnn.DRAM_MEMORY_CONFIG | |
| def open_device(l1_small_size: int = 98304): # convs (VAE) keep their config tensors in L1_SMALL | |
| return ttnn.open_mesh_device(mesh_shape=ttnn.MeshShape(1, 1), | |
| dispatch_core_config=ttnn.DispatchCoreConfig(ttnn.DispatchCoreType.WORKER), | |
| l1_small_size=l1_small_size) | |
| def close_device(dev): | |
| ttnn.close_mesh_device(dev) | |
| def dram_stats(dev) -> dict: | |
| try: | |
| s = ttnn.get_memory_view(dev, ttnn.BufferType.DRAM) | |
| return {"allocated_bytes": s.total_bytes_allocated_per_bank * s.num_banks, | |
| "free_bytes": s.total_bytes_free_per_bank * s.num_banks} | |
| except Exception: # pragma: no cover - diagnostics only | |
| return {} | |
| class Precision: | |
| weight_dtype: ttnn.DataType = ttnn.bfloat16 | |
| mm_fidelity: ttnn.MathFidelity = ttnn.MathFidelity.HiFi2 | |
| sdpa_fidelity: ttnn.MathFidelity = ttnn.MathFidelity.HiFi4 | |
| sdpa_fp32_acc: bool = True | |
| def _dev(dev, t: torch.Tensor, dtype=ttnn.bfloat16): | |
| return ttnn.from_torch(t.contiguous(), dtype=dtype, layout=ttnn.TILE_LAYOUT, device=dev, memory_config=MEM) | |
| def _row(dev, v: torch.Tensor): | |
| """[D] -> [1, 1, 1, D] bf16 row (norm gamma, shift, gate, bias).""" | |
| return _dev(dev, v.to(torch.bfloat16).reshape(1, 1, 1, -1)) | |
| TILE = 32 | |
| SEQ_MULTIPLE = 128 # sequence lengths are padded to multiples of this at least (SDPA chunk sizes divide it) | |
| NEG = -1e9 # additive mask value for excluded keys (finite, representable in bf16) | |
| def linear_to_mm(w: torch.Tensor) -> torch.Tensor: | |
| """nn.Linear weight [out, in] -> matmul weight [in, out].""" | |
| return w.t().contiguous() | |
| def interleave_pairs_permutation(head_dim: int) -> torch.Tensor: | |
| """new[j] = old[p[j]]: rotate-half pairs (i, i + D/2) -> adjacent pairs (2i, 2i + 1). | |
| Applying it to the rows of q_proj/k_proj (per head) and to q_norm/k_norm leaves every q.k product unchanged and | |
| lets tt's rotary_embedding_llama (adjacent pairs) replace upstream's rotate_half RoPE.""" | |
| half = head_dim // 2 | |
| p = torch.empty(head_dim, dtype=torch.long) | |
| p[0::2] = torch.arange(half) | |
| p[1::2] = torch.arange(half) + half | |
| return p | |
| def permute_heads_rows(w_out_in: torch.Tensor, n_heads: int, head_dim: int, perm: torch.Tensor) -> torch.Tensor: | |
| out, inp = w_out_in.shape | |
| assert out == n_heads * head_dim | |
| return w_out_in.view(n_heads, head_dim, inp)[:, perm, :].reshape(out, inp).contiguous() | |
| def rot_transformation_mat(tile: int = TILE) -> torch.Tensor: | |
| """[1, 1, 32, 32] T with (x @ T)[2k] = -x[2k+1], (x @ T)[2k+1] = x[2k] (adjacent-pair rotation).""" | |
| m = torch.zeros(1, 1, tile, tile) | |
| m[..., torch.arange(0, tile, 2), torch.arange(1, tile, 2)] = 1.0 | |
| m[..., torch.arange(1, tile, 2), torch.arange(0, tile, 2)] = -1.0 | |
| return m | |
| def rms(x: torch.Tensor, w: torch.Tensor, eps: float) -> torch.Tensor: | |
| return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + eps) * w | |
| def round_up(n: int, m: int = SEQ_MULTIPLE) -> int: | |
| return (n + m - 1) // m * m | |
| def swiglu_interleave(gate_out_in: torch.Tensor, up_out_in: torch.Tensor, tile: int = TILE) -> torch.Tensor: | |
| """[K, 2N] weight for minimal_matmul(fuse_swiglu=True): column tile 2p = gate tile p, 2p+1 = up tile p.""" | |
| g, u = linear_to_mm(gate_out_in), linear_to_mm(up_out_in) | |
| K, N = g.shape | |
| assert N % tile == 0, N | |
| return torch.stack([g.view(K, N // tile, tile), u.view(K, N // tile, tile)], dim=2).reshape(K, 2 * N).contiguous() | |
| def apply_rope_adjacent(x: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor: | |
| rot = torch.stack([-x[..., 1::2], x[..., 0::2]], dim=-1).flatten(-2) | |
| return x * cos + rot * sin | |