src/api/native_tensor_attn2.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Native bodies for the second attention family (see | ||
| 2 | // native_tensor_attn2_decl.h): decomposed 2D rel-pos self-attention (global + | ||
| 3 | // windowed), packed variable-length flash attention, the gated delta rule and | ||
| 4 | // M-RoPE. js/tensor_attn2.js checks argument types; a body checks the index | ||
| 5 | // streams' values (see IdxStream), calls, and records any thrown violation. | ||
| 6 | |||
| 7 | #include "native_tensor_attn2_decl.h" | ||
| 8 | #include "api_internal.h" | ||
| 9 | #include "native_register.h" | ||
| 10 | #include "native_tensor_extra_util.h" | ||
| 11 | |||
| 12 | #include <string> | ||
| 13 | #include <vector> | ||
| 14 | |||
| 15 | using namespace brotensor::api; | ||
| 16 | using brotensor::Tensor; | ||
| 17 | |||
| 18 | namespace { | ||
| 19 | |||
| 20 | 74 | Tensor* T(void* p) { return toTensor(p); } | |
| 21 | |||
| 22 | // The varlen / M-RoPE ops take `const int32_t*` streams (device pointers on | ||
| 23 | // CUDA/Metal, host on CPU) whose VALUES address rows of the other operands, | ||
| 24 | // and the kernels trust them. A stream is an optional GpuTensor holding INT32 | ||
| 25 | // (uploadInt32) or whole-number FP32 (upload); the native reads it back, | ||
| 26 | // checks every value, and hands the op INT32 storage — the tensor's own, or | ||
| 27 | // an INT32 copy held in `scratch` (reading FP32 storage as INT32 would turn | ||
| 28 | // 1.0f into 1065353216). | ||
| 29 | 58 | struct IdxStream { | |
| 30 | std::vector<int32_t> vals; | ||
| 31 | Tensor scratch; | ||
| 32 | 58 | const int32_t* ptr = nullptr; | |
| 33 | }; | ||
| 34 | |||
| 35 | // Reads `n` values of the stream in `bits` into `s`; a null stream leaves | ||
| 36 | // s.ptr null (the op decides whether that is allowed). | ||
| 37 | 28 | bool readStream(const char* L, const char* name, uint64_t bits, int64_t n, IdxStream& s) { | |
| 38 | 28 | const Tensor* t = tensorFromValue(bits); | |
| 39 |
1/2✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
|
28 | if (!t) return true; |
| 40 |
2/2✓ Branch 0 taken 26 times.
✓ Branch 1 taken 2 times.
|
28 | if (!extra::hostInt32(L, name, t, n, s.vals)) return false; |
| 41 | 26 | s.ptr = static_cast<const int32_t*>(extra::int32Operand(*t, s.vals, s.scratch).data); | |
| 42 | 26 | return true; | |
| 43 | 28 | } | |
| 44 | |||
| 45 | // cu_seqlens: batch+1 non-decreasing prefix sums inside [0, total], each | ||
| 46 | // sequence at most maxLen long (the GPU kernels size their tiles from it). | ||
| 47 | 20 | bool needCuSeq(const char* L, const char* name, uint64_t bits, int32_t batch, int64_t total, int32_t maxLen, | |
| 48 | IdxStream& s) { | ||
| 49 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
|
20 | if (batch <= 0) return true; |
| 50 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 2 times.
|
20 | if (!tensorFromValue(bits)) { |
| 51 |
4/8✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | setError(std::string(L) + ": " + name + " is required when batch > 0"); |
| 52 | 2 | return false; | |
| 53 | } | ||
| 54 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!readStream(L, name, bits, static_cast<int64_t>(batch) + 1, s)) return false; |
| 55 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 2 times.
|
18 | if (!extra::needIndicesIn(L, name, s.vals, static_cast<int64_t>(batch) + 1, 0, total + 1)) return false; |
| 56 |
2/2✓ Branch 0 taken 30 times.
✓ Branch 1 taken 12 times.
|
42 | for (int32_t b = 0; b < batch; ++b) { |
| 57 | 30 | const int64_t len = static_cast<int64_t>(s.vals[b + 1]) - s.vals[b]; | |
| 58 |
4/4✓ Branch 0 taken 28 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 26 times.
✓ Branch 3 taken 2 times.
|
30 | if (len < 0 || len > maxLen) { |
| 59 |
8/16✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 4 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 4 times.
✗ Branch 15 not taken.
|
12 | setError(std::string(L) + ": " + name + " sequence " + std::to_string(b) + " has length " + |
| 60 |
5/10✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
|
8 | std::to_string(len) + " (must be in [0, " + std::to_string(maxLen) + "])"); |
| 61 | 4 | return false; | |
| 62 | } | ||
| 63 | 26 | } | |
| 64 | 12 | return true; | |
| 65 | 20 | } | |
| 66 | |||
| 67 | // An M-RoPE position stream for an axis of width d: length L, every value a | ||
| 68 | // row of that axis's cos/sin tables. | ||
| 69 | 18 | bool needPosStream(const char* L, const char* name, uint64_t bits, int32_t d, int64_t rows, const Tensor* cosT, | |
| 70 | const Tensor* sinT, IdxStream& s) { | ||
| 71 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 12 times.
|
18 | if (d <= 0) return true; |
| 72 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 2 times.
|
12 | if (!tensorFromValue(bits)) { |
| 73 |
4/8✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
2 | setError(std::string(L) + ": " + name + " is required when its axis width is > 0"); |
| 74 | 2 | return false; | |
| 75 | } | ||
| 76 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | if (!readStream(L, name, bits, rows, s)) return false; |
| 77 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | const int64_t maxPos = cosT->rows < sinT->rows ? cosT->rows : sinT->rows; |
| 78 | 8 | return extra::needIndicesIn(L, name, s.vals, rows, 0, maxPos); | |
| 79 | 18 | } | |
| 80 | |||
| 81 | } // namespace | ||
| 82 | |||
| 83 | extern "C" { | ||
| 84 | |||
| 85 | // ---- SAM / ViTDet decomposed 2D rel-pos self-attention --------------------- | ||
| 86 | |||
| 87 | 4 | void bro_tensor_selfAttentionDecomposedRelPosForward(void* X, void* Wq, uint64_t bq_bits, void* Wk, uint64_t bk_bits, | |
| 88 | void* Wv, uint64_t bv_bits, void* Wo, uint64_t bo_bits, | ||
| 89 | void* relPosH, void* relPosW, | ||
| 90 | int32_t numHeads, int32_t gridH, int32_t gridW, double scale, | ||
| 91 | void* O) { | ||
| 92 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!need("selfAttentionDecomposedRelPosForward", {X, Wq, Wk, Wv, Wo, relPosH, relPosW, O})) return; |
| 93 | BROTENSOR_API_TRY | ||
| 94 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | brotensor::self_attention_decomposed_rel_pos_forward( |
| 95 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | *toTensor(X), |
| 96 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wq), tensorFromValue(bq_bits), |
| 97 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wk), tensorFromValue(bk_bits), |
| 98 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wv), tensorFromValue(bv_bits), |
| 99 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wo), tensorFromValue(bo_bits), |
| 100 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(relPosH), *toTensor(relPosW), |
| 101 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | numHeads, gridH, gridW, static_cast<float>(scale), *toTensor(O)); |
| 102 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
4 | BROTENSOR_API_CATCH("selfAttentionDecomposedRelPosForward") |
| 103 | 4 | } | |
| 104 | |||
| 105 | 4 | void bro_tensor_selfAttentionDecomposedRelPosWindowedForward(void* X, void* Wq, uint64_t bq_bits, void* Wk, uint64_t bk_bits, | |
| 106 | void* Wv, uint64_t bv_bits, void* Wo, uint64_t bo_bits, | ||
| 107 | void* relPosH, void* relPosW, | ||
| 108 | int32_t numHeads, int32_t gridH, int32_t gridW, | ||
| 109 | int32_t window, double scale, void* O) { | ||
| 110 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!need("selfAttentionDecomposedRelPosWindowedForward", {X, Wq, Wk, Wv, Wo, relPosH, relPosW, O})) return; |
| 111 | BROTENSOR_API_TRY | ||
| 112 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | brotensor::self_attention_decomposed_rel_pos_windowed_forward( |
| 113 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | *toTensor(X), |
| 114 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wq), tensorFromValue(bq_bits), |
| 115 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wk), tensorFromValue(bk_bits), |
| 116 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wv), tensorFromValue(bv_bits), |
| 117 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(Wo), tensorFromValue(bo_bits), |
| 118 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(relPosH), *toTensor(relPosW), |
| 119 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | numHeads, gridH, gridW, window, static_cast<float>(scale), *toTensor(O)); |
| 120 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
4 | BROTENSOR_API_CATCH("selfAttentionDecomposedRelPosWindowedForward") |
| 121 | 4 | } | |
| 122 | |||
| 123 | // ---- packed variable-length flash attention (Qwen-VL window attention) ----- | ||
| 124 | |||
| 125 | 12 | void bro_tensor_flashAttentionVarlenForward(void* Q, void* K, void* V, uint64_t cuSeqQ_bits, uint64_t cuSeqK_bits, | |
| 126 | int32_t batch, int32_t maxQ, int32_t maxK, | ||
| 127 | int32_t numHeads, int32_t headDim, bool causal, void* O) { | ||
| 128 | 12 | const char* L = "flashAttentionVarlenForward"; | |
| 129 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
|
12 | if (!need(L, {Q, K, V, O}) || !needNonNegative(L, {batch, maxQ, maxK})) return; |
| 130 | BROTENSOR_API_TRY | ||
| 131 | 12 | IdxStream cq, ck; | |
| 132 |
5/8✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
16 | if (!needCuSeq(L, "cuSeqQ", cuSeqQ_bits, batch, T(Q)->rows, maxQ, cq) || |
| 133 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
12 | !needCuSeq(L, "cuSeqK", cuSeqK_bits, batch, T(K)->rows, maxK, ck)) return; |
| 134 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
8 | brotensor::flash_attention_varlen_forward(*toTensor(Q), *toTensor(K), *toTensor(V), |
| 135 | 4 | cq.ptr, ck.ptr, | |
| 136 | 4 | batch, maxQ, maxK, numHeads, headDim, causal, | |
| 137 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | *toTensor(O)); |
| 138 |
2/15✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 8 times.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
12 | BROTENSOR_API_CATCH(L) |
| 139 | 12 | } | |
| 140 | |||
| 141 | 2 | void bro_tensor_flashAttentionVarlenBackward(void* Q, void* K, void* V, void* O, void* dO, | |
| 142 | uint64_t cuSeqQ_bits, uint64_t cuSeqK_bits, | ||
| 143 | int32_t batch, int32_t maxQ, int32_t maxK, | ||
| 144 | int32_t numHeads, int32_t headDim, bool causal, | ||
| 145 | void* dQ, void* dK, void* dV) { | ||
| 146 | 2 | const char* L = "flashAttentionVarlenBackward"; | |
| 147 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (!need(L, {Q, K, V, O, dO, dQ, dK, dV}) || !needNonNegative(L, {batch, maxQ, maxK})) return; |
| 148 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
|
2 | if (!needPair(L, "O", T(O), T(Q)) || !needPair(L, "dO", T(dO), T(Q))) return; |
| 149 | BROTENSOR_API_TRY | ||
| 150 | 2 | IdxStream cq, ck; | |
| 151 |
4/8✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
4 | if (!needCuSeq(L, "cuSeqQ", cuSeqQ_bits, batch, T(Q)->rows, maxQ, cq) || |
| 152 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | !needCuSeq(L, "cuSeqK", cuSeqK_bits, batch, T(K)->rows, maxK, ck)) return; |
| 153 |
4/8✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
|
4 | brotensor::flash_attention_varlen_backward(*toTensor(Q), *toTensor(K), *toTensor(V), |
| 154 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | *toTensor(O), *toTensor(dO), |
| 155 | 2 | cq.ptr, ck.ptr, | |
| 156 | 2 | batch, maxQ, maxK, numHeads, headDim, causal, | |
| 157 |
3/6✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
2 | *toTensor(dQ), *toTensor(dK), *toTensor(dV)); |
| 158 |
1/15✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✓ Branch 12 taken 2 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
2 | BROTENSOR_API_CATCH(L) |
| 159 | 2 | } | |
| 160 | |||
| 161 | // ---- gated delta rule (linear attention — Qwen3-Next) --------------------- | ||
| 162 | |||
| 163 | 4 | void bro_tensor_gatedDeltaRuleChunked(void* Q, void* K, void* V, void* aRaw, void* beta, void* logA, | |
| 164 | int32_t numHeads, int32_t d_k, int32_t d_v, void* state, void* O) { | ||
| 165 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!need("gatedDeltaRuleChunked", {Q, K, V, aRaw, beta, logA, state, O})) return; |
| 166 | BROTENSOR_API_TRY | ||
| 167 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
8 | brotensor::gated_delta_rule_chunked(*toTensor(Q), *toTensor(K), *toTensor(V), |
| 168 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
4 | *toTensor(aRaw), *toTensor(beta), *toTensor(logA), |
| 169 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | numHeads, d_k, d_v, *toTensor(state), *toTensor(O)); |
| 170 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
4 | BROTENSOR_API_CATCH("gatedDeltaRuleChunked") |
| 171 | 4 | } | |
| 172 | |||
| 173 | 6 | void bro_tensor_gatedDeltaRuleStep(void* Q, void* K, void* V, void* aRaw, void* beta, void* logA, | |
| 174 | int32_t numHeads, int32_t d_k, int32_t d_v, void* state, void* O) { | ||
| 175 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!need("gatedDeltaRuleStep", {Q, K, V, aRaw, beta, logA, state, O})) return; |
| 176 | BROTENSOR_API_TRY | ||
| 177 |
4/8✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 6 times.
✗ Branch 7 not taken.
|
12 | brotensor::gated_delta_rule_step(*toTensor(Q), *toTensor(K), *toTensor(V), |
| 178 |
3/6✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
6 | *toTensor(aRaw), *toTensor(beta), *toTensor(logA), |
| 179 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | numHeads, d_k, d_v, *toTensor(state), *toTensor(O)); |
| 180 |
0/12✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
6 | BROTENSOR_API_CATCH("gatedDeltaRuleStep") |
| 181 | 6 | } | |
| 182 | |||
| 183 | // ---- M-RoPE (Qwen-VL multimodal rotary) ----------------------------------- | ||
| 184 | |||
| 185 | 10 | void bro_tensor_ropeApplyMrope(void* X, void* cosT, void* sinT, void* cosH, void* sinH, void* cosW, void* sinW, | |
| 186 | uint64_t posT_bits, uint64_t posH_bits, uint64_t posW_bits, | ||
| 187 | int32_t headDim, int32_t numHeads, int32_t d_t, int32_t d_h, int32_t d_w, | ||
| 188 | void* Y) { | ||
| 189 | 10 | const char* L = "ropeApplyMrope"; | |
| 190 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!need(L, {X, cosT, sinT, cosH, sinH, cosW, sinW, Y})) return; |
| 191 | 10 | const int64_t rows = T(X)->rows; | |
| 192 | BROTENSOR_API_TRY | ||
| 193 | 10 | IdxStream pt, ph, pw; | |
| 194 |
6/10✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 6 times.
✓ Branch 8 taken 4 times.
✗ Branch 9 not taken.
|
14 | if (!needPosStream(L, "posT", posT_bits, d_t, rows, T(cosT), T(sinT), pt) || |
| 195 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
|
4 | !needPosStream(L, "posH", posH_bits, d_h, rows, T(cosH), T(sinH), ph) || |
| 196 |
3/6✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
|
10 | !needPosStream(L, "posW", posW_bits, d_w, rows, T(cosW), T(sinW), pw)) return; |
| 197 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | brotensor::rope_apply_mrope(*toTensor(X), |
| 198 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(cosT), *toTensor(sinT), |
| 199 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(cosH), *toTensor(sinH), |
| 200 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | *toTensor(cosW), *toTensor(sinW), |
| 201 | 4 | pt.ptr, ph.ptr, pw.ptr, | |
| 202 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | headDim, numHeads, d_t, d_h, d_w, *toTensor(Y)); |
| 203 |
2/15✗ Branch 0 not taken.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✓ Branch 11 taken 6 times.
✓ Branch 12 taken 4 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
|
10 | BROTENSOR_API_CATCH(L) |
| 204 | 10 | } | |
| 205 | |||
| 206 | } // extern "C" | ||
| 207 | |||
| 208 | namespace brotensor::api { | ||
| 209 | |||
| 210 | 3 | bool registerTensorNatives_attn2(std::string* error) { | |
| 211 | using namespace brotensor::api::reg; | ||
| 212 | 3 | return | |
| 213 | 6 | fn("__bro_native.tensor.selfAttentionDecomposedRelPosForward", p(&bro_tensor_selfAttentionDecomposedRelPosForward), "void", | |
| 214 | 3 | {kTensorCls, kTensorCls, kDyn, kTensorCls, kDyn, kTensorCls, kDyn, kTensorCls, kDyn, | |
| 215 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | kTensorCls, kTensorCls, "i32", "i32", "i32", "f64", kTensorCls}, error) && |
| 216 | 6 | fn("__bro_native.tensor.selfAttentionDecomposedRelPosWindowedForward", p(&bro_tensor_selfAttentionDecomposedRelPosWindowedForward), "void", | |
| 217 | 3 | {kTensorCls, kTensorCls, kDyn, kTensorCls, kDyn, kTensorCls, kDyn, kTensorCls, kDyn, | |
| 218 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | kTensorCls, kTensorCls, "i32", "i32", "i32", "i32", "f64", kTensorCls}, error) && |
| 219 | 6 | fn("__bro_native.tensor.flashAttentionVarlenForward", p(&bro_tensor_flashAttentionVarlenForward), "void", | |
| 220 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | {kTensorCls, kTensorCls, kTensorCls, kDyn, kDyn, "i32", "i32", "i32", "i32", "i32", "bool", kTensorCls}, error) && |
| 221 | 6 | fn("__bro_native.tensor.flashAttentionVarlenBackward", p(&bro_tensor_flashAttentionVarlenBackward), "void", | |
| 222 | 3 | {kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, kDyn, kDyn, | |
| 223 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | "i32", "i32", "i32", "i32", "i32", "bool", kTensorCls, kTensorCls, kTensorCls}, error) && |
| 224 | 6 | fn("__bro_native.tensor.gatedDeltaRuleChunked", p(&bro_tensor_gatedDeltaRuleChunked), "void", | |
| 225 | 3 | {kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, | |
| 226 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
6 | "i32", "i32", "i32", kTensorCls, kTensorCls}, error) && |
| 227 | 6 | fn("__bro_native.tensor.gatedDeltaRuleStep", p(&bro_tensor_gatedDeltaRuleStep), "void", | |
| 228 | 3 | {kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, | |
| 229 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
6 | "i32", "i32", "i32", kTensorCls, kTensorCls}, error) && |
| 230 | 6 | fn("__bro_native.tensor.ropeApplyMrope", p(&bro_tensor_ropeApplyMrope), "void", | |
| 231 | 3 | {kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, kTensorCls, | |
| 232 | 3 | kDyn, kDyn, kDyn, "i32", "i32", "i32", "i32", "i32", kTensorCls}, error); | |
| 233 | } | ||
| 234 | |||
| 235 | } // namespace brotensor::api | ||
| 236 |