Download runtime/optimizations/b1_runtime_joint_projection.py from rockmatrix-ai/EdgeRock: direct link, hf CLI and curl.
- Browser
- Download file 3.7 kB
-
https://huggingface.co/rockmatrix-ai/EdgeRock/resolve/main/runtime/optimizations/b1_runtime_joint_projection.py
- Command line
-
hf download hf://rockmatrix-ai/EdgeRock/runtime/optimizations/b1_runtime_joint_projection.py
-
curl -L -o b1_runtime_joint_projection.py https://huggingface.co/rockmatrix-ai/EdgeRock/resolve/main/runtime/optimizations/b1_runtime_joint_projection.py
3.7 kB
| from types import MethodType | |
| import torch | |
| import torch.nn.functional as F | |
| import triton | |
| import triton.language as tl | |
| base_linear = F.linear | |
| checks = [] | |
| checked = set() | |
| writer_owners = {} | |
| def joint_matvec(X, Q, W, A, Y, NQ: tl.constexpr, NW: tl.constexpr, | |
| NA: tl.constexpr, K: tl.constexpr, BK: tl.constexpr): | |
| start = tl.program_id(0) * 2 | |
| rows = start + tl.arange(0, 2) | |
| columns = tl.arange(0, BK) | |
| x = tl.load(X + columns, columns < K, 0).to(tl.float32) | |
| if start < NQ: | |
| weights = Q + rows[:, None] * K + columns[None, :] | |
| elif start < NQ + NW: | |
| weights = W + (rows[:, None] - NQ) * K + columns[None, :] | |
| else: | |
| weights = A + (rows[:, None] - NQ - NW) * K + columns[None, :] | |
| weight = tl.load(weights, | |
| (rows[:, None] < NQ + NW + NA) & (columns[None, :] < K), 0).to(tl.float32) | |
| result = tl.sum(weight * x[None, :], axis=1) | |
| tl.store(Y + rows, result, rows < NQ + NW + NA) | |
| def writer_linear(values, weight, bias=None): | |
| owner = writer_owners.get(weight.data_ptr()) | |
| if owner is not None and owner._b1_joint_active and values.numel() == values.shape[-1]: | |
| begin = owner.q_proj.out_features | |
| result = owner._b1_joint_output[..., begin:begin + weight.shape[0]].reshape(*values.shape[:-1], weight.shape[0]) | |
| owner._b1_joint_active = False | |
| owner._b1_joint_output = None | |
| return result | |
| return base_linear(values, weight, bias) | |
| def install(model): | |
| for m in model.modules(): | |
| if not (hasattr(m, '_query_scores') and hasattr(m, '_inference_writer_gate_up')): | |
| continue | |
| m._b1_joint_output = None | |
| m._b1_joint_active = False | |
| writer_owners[m._inference_writer_gate_up.data_ptr()] = m | |
| previous_query, previous_admission = m.q_proj.forward, m.admission_down.forward | |
| assert all(w.is_contiguous() and w.shape[0] % 2 == 0 for w in | |
| (m.q_proj.weight, m._inference_writer_gate_up, m.admission_down.weight)) | |
| def query(projection, values, *args, owner=m, previous=previous_query, **kwargs): | |
| owner._b1_joint_active = values.numel() == values.shape[-1] | |
| if not owner._b1_joint_active: | |
| return previous(values, *args, **kwargs) | |
| q, w, a = owner.q_proj.weight, owner._inference_writer_gate_up, owner.admission_down.weight | |
| n = q.shape[0] + w.shape[0] + a.shape[0] | |
| output = values.new_empty((*values.shape[:-1], n)) | |
| joint_matvec[triton.cdiv(n, 2),](values, q, w, a, output, | |
| q.shape[0], w.shape[0], a.shape[0], q.shape[1], | |
| triton.next_power_of_2(q.shape[1]), num_warps=4, num_stages=1) | |
| if owner not in checked: | |
| expected = torch.cat([base_linear(values, weight) for weight in (q, w, a)], -1) | |
| checks.append(dict(layer=len(checks), shape=list(output.shape), | |
| exact=bool(torch.equal(expected, output)), finite=bool(output.isfinite().all()), | |
| max_abs=float((expected.float() - output.float()).abs().max()))) | |
| checked.add(owner) | |
| owner._b1_joint_output = output | |
| return output[..., :q.shape[0]] | |
| def admission(projection, values, *args, owner=m, previous=previous_admission, **kwargs): | |
| if not owner._b1_joint_active: | |
| return previous(values, *args, **kwargs) | |
| return owner._b1_joint_output[..., -owner.admission_down.out_features:] | |
| m.q_proj.forward = MethodType(query, m.q_proj) | |
| m.admission_down.forward = MethodType(admission, m.admission_down) | |
| assert len(writer_owners) == 8 | |
| F.linear = writer_linear | |