@@ -1013,14 +1013,22 @@ void channelwise_gated_delta_rule_chunked(
10131013 const auto * __restrict__ beta_c = beta_head + base;
10141014 auto * __restrict__ o_c = o_head + base * v_head_dim;
10151015
1016- // 1. gc = cumsum_r(log decay) (per channel; resets each chunk)
1017- for (const auto k_idx : c10::irange (k_head_dim)) {
1018- float acc = 0 .0f ;
1019- for (const auto r : c10::irange (cur)) {
1020- acc += std::log (d_c[r * k_head_dim + k_idx]);
1021- sc.gc [r * k_head_dim + k_idx] = acc;
1022- sc.eg [r * k_head_dim + k_idx] = std::exp (acc);
1023- sc.eg_inv [r * k_head_dim + k_idx] = std::exp (-acc);
1016+ // 1. gc = cumsum_r(log decay) (per channel; resets each chunk).
1017+ // Reordered so the inner loop runs contiguously over k; the running
1018+ // cumsum is read back from the previous gc row.
1019+ for (const auto r : c10::irange (cur)) {
1020+ const float * __restrict__ d_row = d_c + r * k_head_dim;
1021+ const float * __restrict__ gc_prev =
1022+ r == 0 ? nullptr : sc.gc + (r - 1 ) * k_head_dim;
1023+ float * __restrict__ gc_row = sc.gc + r * k_head_dim;
1024+ float * __restrict__ eg_row = sc.eg + r * k_head_dim;
1025+ float * __restrict__ eg_inv_row = sc.eg_inv + r * k_head_dim;
1026+ for (const auto k_idx : c10::irange (k_head_dim)) {
1027+ const float prev = gc_prev == nullptr ? 0 .0f : gc_prev[k_idx];
1028+ const float acc = prev + std::log (d_row[k_idx]);
1029+ gc_row[k_idx] = acc;
1030+ eg_row[k_idx] = std::exp (acc);
1031+ eg_inv_row[k_idx] = std::exp (-acc);
10241032 }
10251033 }
10261034
@@ -1073,47 +1081,64 @@ void channelwise_gated_delta_rule_chunked(
10731081 }
10741082
10751083 // 4. WY packing: w = A @ (exp(gc) * k), u = A @ v (A lower-tri: j
1076- // <= r)
1084+ // <= r). Reordered so the inner loop runs contiguously over k / v.
10771085 for (const auto r : c10::irange (cur)) {
1086+ float * __restrict__ w_row = sc.w + r * k_head_dim;
1087+ float * __restrict__ u_row = sc.u + r * v_head_dim;
10781088 for (const auto k_idx : c10::irange (k_head_dim)) {
1079- float acc = 0 .0f ;
1080- for (const auto j : c10::irange (r + 1 )) {
1081- acc += sc.A [r * CHUNK_SIZE + j] *
1082- sc.eg [j * k_head_dim + k_idx] *
1083- k_c[j * k_head_dim + k_idx];
1084- }
1085- sc.w [r * k_head_dim + k_idx] = acc;
1089+ w_row[k_idx] = 0 .0f ;
10861090 }
10871091 for (const auto v_idx : c10::irange (v_head_dim)) {
1088- float acc = 0 .0f ;
1089- for (const auto j : c10::irange (r + 1 )) {
1090- acc += sc.A [r * CHUNK_SIZE + j] * v_c[j * v_head_dim + v_idx];
1092+ u_row[v_idx] = 0 .0f ;
1093+ }
1094+ for (const auto j : c10::irange (r + 1 )) {
1095+ const float arj = sc.A [r * CHUNK_SIZE + j];
1096+ const float * __restrict__ eg_row = sc.eg + j * k_head_dim;
1097+ const float * __restrict__ k_row = k_c + j * k_head_dim;
1098+ for (const auto k_idx : c10::irange (k_head_dim)) {
1099+ w_row[k_idx] += arj * eg_row[k_idx] * k_row[k_idx];
1100+ }
1101+ const float * __restrict__ v_row = v_c + j * v_head_dim;
1102+ for (const auto v_idx : c10::irange (v_head_dim)) {
1103+ u_row[v_idx] += arj * v_row[v_idx];
10911104 }
1092- sc.u [r * v_head_dim + v_idx] = acc;
10931105 }
10941106 }
10951107
1096- // 5. pv = u - w @ S_old ; o = (q ⊙ exp gc) @ S_old + Aqk @ pv
1108+ // 5. pv = u - w @ S_old ; o = (q ⊙ exp gc) @ S_old. Reordered so
1109+ // the inner loop runs contiguously over v; pv/o_c accumulate the
1110+ // k-sum, then pv is finalized as u - (w@S) with a single
1111+ // subtraction (bit-identical to the k-then-subtract form).
10971112 for (const auto r : c10::irange (cur)) {
1113+ float * __restrict__ pv_row = sc.pv + r * v_head_dim;
1114+ float * __restrict__ o_row = o_c + r * v_head_dim;
10981115 for (const auto v_idx : c10::irange (v_head_dim)) {
1099- float wS = 0 .0f , qS = 0 .0f ;
1100- for (const auto k_idx : c10::irange (k_head_dim)) {
1101- const float s = S[k_idx * v_head_dim + v_idx];
1102- wS += sc.w [r * k_head_dim + k_idx] * s;
1103- qS += q_c[r * k_head_dim + k_idx] *
1104- sc.eg [r * k_head_dim + k_idx] * s;
1116+ pv_row[v_idx] = 0 .0f ;
1117+ o_row[v_idx] = 0 .0f ;
1118+ }
1119+ for (const auto k_idx : c10::irange (k_head_dim)) {
1120+ const float wrk = sc.w [r * k_head_dim + k_idx];
1121+ const float qrk =
1122+ q_c[r * k_head_dim + k_idx] * sc.eg [r * k_head_dim + k_idx];
1123+ const float * __restrict__ s_row = S + k_idx * v_head_dim;
1124+ for (const auto v_idx : c10::irange (v_head_dim)) {
1125+ pv_row[v_idx] += wrk * s_row[v_idx];
1126+ o_row[v_idx] += qrk * s_row[v_idx];
11051127 }
1106- sc.pv [r * v_head_dim + v_idx] =
1107- sc.u [r * v_head_dim + v_idx] - wS;
1108- o_c[r * v_head_dim + v_idx] = qS;
1128+ }
1129+ const float * __restrict__ u_row = sc.u + r * v_head_dim;
1130+ for (const auto v_idx : c10::irange (v_head_dim)) {
1131+ pv_row[v_idx] = u_row[v_idx] - pv_row[v_idx];
11091132 }
11101133 }
1134+ // 5b. o += Aqk @ pv (AXPY over the contiguous v).
11111135 for (const auto r : c10::irange (cur)) {
1136+ float * __restrict__ o_row = o_c + r * v_head_dim;
11121137 for (const auto j : c10::irange (r + 1 )) {
11131138 const float a = sc.Aqk [r * CHUNK_SIZE + j];
1139+ const float * __restrict__ pv_row = sc.pv + j * v_head_dim;
11141140 for (const auto v_idx : c10::irange (v_head_dim)) {
1115- o_c[r * v_head_dim + v_idx] +=
1116- a * sc.pv [j * v_head_dim + v_idx];
1141+ o_row[v_idx] += a * pv_row[v_idx];
11171142 }
11181143 }
11191144 }
@@ -1129,13 +1154,16 @@ void channelwise_gated_delta_rule_chunked(
11291154 for (const auto r : c10::irange (cur)) {
11301155 sc.de [r] = std::exp (gc_last - sc.gc [r * k_head_dim + k_idx]);
11311156 }
1157+ float * __restrict__ S_row = S + k_idx * v_head_dim;
11321158 for (const auto v_idx : c10::irange (v_head_dim)) {
1133- float acc = S[k_idx * v_head_dim + v_idx] * eg_last;
1134- for (const auto r : c10::irange (cur)) {
1135- acc += k_c[r * k_head_dim + k_idx] * sc.de [r] *
1136- sc.pv [r * v_head_dim + v_idx];
1159+ S_row[v_idx] *= eg_last;
1160+ }
1161+ for (const auto r : c10::irange (cur)) {
1162+ const float c = k_c[r * k_head_dim + k_idx] * sc.de [r];
1163+ const float * __restrict__ pv_row = sc.pv + r * v_head_dim;
1164+ for (const auto v_idx : c10::irange (v_head_dim)) {
1165+ S_row[v_idx] += c * pv_row[v_idx];
11371166 }
1138- S[k_idx * v_head_dim + v_idx] = acc;
11391167 }
11401168 }
11411169 } // chunk
@@ -1311,4 +1339,4 @@ const auto channelwise_gated_delta_rule_out_registration =
13111339 " llama::channelwise_gated_delta_rule.out" ,
13121340 channelwise_gated_delta_rule_out_boxed));
13131341
1314- } // namespace
1342+ } // namespace
0 commit comments