Qwen changes
Browse files- generate_imatrix.py +90 -39
- hexstate_quantize.c +89 -57
- hpc_forward_merged.c +44 -34
generate_imatrix.py
CHANGED
|
@@ -166,6 +166,8 @@ class GGUFModel:
|
|
| 166 |
'rope_base': self.kv.get(f'{arch}.rope.freq_base', 10000.0),
|
| 167 |
'swa_window': self.kv.get(f'{arch}.attention.sliding_window', 0),
|
| 168 |
'head_dim': head_dim,
|
|
|
|
|
|
|
| 169 |
}
|
| 170 |
|
| 171 |
def get_tensor_f32(self, name):
|
|
@@ -643,7 +645,7 @@ class TransformerRunner:
|
|
| 643 |
imp_fu_p, cnt_fu_p = make_imp(f'{pfx}.ffn_up.weight', n_embd if ffn_up_w is not None else 0)
|
| 644 |
imp_fd_p, cnt_fd_p = make_imp(f'{pfx}.ffn_down.weight', ffn_d if ffn_down_w is not None else 0)
|
| 645 |
|
| 646 |
-
# Call C function — entire layer in one call
|
| 647 |
lib.hexstate_forward_layer(
|
| 648 |
h_ptr,
|
| 649 |
norm_p,
|
|
@@ -669,16 +671,97 @@ class TransformerRunner:
|
|
| 669 |
ctypes.c_int64(n_head), ctypes.c_int64(n_head_kv),
|
| 670 |
ctypes.c_int64(head_dim), ctypes.c_float(eps))
|
| 671 |
|
| 672 |
-
# Read back importance
|
| 673 |
for name, arr, cnt in imp_refs:
|
| 674 |
self.importance[name] = (arr.astype(np.float64), cnt.value)
|
| 675 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 676 |
# Force-free per-layer weight buffers (~1.4 GB) before next layer
|
| 677 |
del refs, imp_refs
|
| 678 |
import gc; gc.collect()
|
| 679 |
|
| 680 |
return hidden
|
| 681 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 682 |
def _hpc_rms_norm(self, x, weight, eps):
|
| 683 |
"""RMS norm via HPC C library, falling back to numpy."""
|
| 684 |
if self._hpc_lib and x.flags['C_CONTIGUOUS']:
|
|
@@ -1055,43 +1138,7 @@ class TransformerRunner:
|
|
| 1055 |
hidden = hidden + ff_out
|
| 1056 |
else:
|
| 1057 |
# MoE path
|
| 1058 |
-
|
| 1059 |
-
if gate_inp_w is not None:
|
| 1060 |
-
self._record(f'{pfx}.ffn_gate_inp.weight', normed_ff)
|
| 1061 |
-
router_logits = normed_ff @ gate_inp_w.T
|
| 1062 |
-
n_experts = router_logits.shape[-1]
|
| 1063 |
-
probs = softmax(router_logits, axis=-1)
|
| 1064 |
-
top2 = np.argsort(probs, axis=-1)[:, -2:]
|
| 1065 |
-
|
| 1066 |
-
ff_out = np.zeros_like(normed_ff)
|
| 1067 |
-
for exp_id in range(n_experts):
|
| 1068 |
-
ew_gate = self._get_weight(f'{pfx}.ffn_gate.{exp_id}.weight')
|
| 1069 |
-
ew_up = self._get_weight(f'{pfx}.ffn_up.{exp_id}.weight')
|
| 1070 |
-
ew_down = self._get_weight(f'{pfx}.ffn_down.{exp_id}.weight')
|
| 1071 |
-
if ew_gate is None:
|
| 1072 |
-
continue
|
| 1073 |
-
|
| 1074 |
-
mask_exp = np.any(top2 == exp_id, axis=-1) # [seq]
|
| 1075 |
-
if not np.any(mask_exp):
|
| 1076 |
-
continue
|
| 1077 |
-
|
| 1078 |
-
exp_input = normed_ff[mask_exp]
|
| 1079 |
-
self._record(f'{pfx}.ffn_gate.{exp_id}.weight', exp_input)
|
| 1080 |
-
self._record(f'{pfx}.ffn_up.{exp_id}.weight', exp_input)
|
| 1081 |
-
|
| 1082 |
-
g = self.act_fn(exp_input @ ew_gate.T)
|
| 1083 |
-
u = exp_input @ ew_up.T
|
| 1084 |
-
mid = g * u
|
| 1085 |
-
self._record(f'{pfx}.ffn_down.{exp_id}.weight', mid)
|
| 1086 |
-
|
| 1087 |
-
exp_out = mid @ ew_down.T
|
| 1088 |
-
# Weight by routing probability
|
| 1089 |
-
for token_idx in np.where(mask_exp)[0]:
|
| 1090 |
-
w = probs[token_idx, exp_id]
|
| 1091 |
-
local_idx = np.sum(mask_exp[:token_idx])
|
| 1092 |
-
ff_out[token_idx] += w * exp_out[local_idx]
|
| 1093 |
-
|
| 1094 |
-
hidden = hidden + ff_out
|
| 1095 |
|
| 1096 |
return hidden
|
| 1097 |
|
|
@@ -1167,6 +1214,8 @@ class TransformerRunner:
|
|
| 1167 |
self._record(f'{pfx}.ffn_down.weight', ff_mid)
|
| 1168 |
ff_out = ff_mid @ down_w.T
|
| 1169 |
hidden = hidden + ff_out
|
|
|
|
|
|
|
| 1170 |
|
| 1171 |
return hidden
|
| 1172 |
|
|
@@ -1308,6 +1357,8 @@ class TransformerRunner:
|
|
| 1308 |
self._record(f'{pfx}.ffn_down.weight', ff_mid)
|
| 1309 |
ff_out = ff_mid @ down_w.T
|
| 1310 |
hidden = hidden + ff_out
|
|
|
|
|
|
|
| 1311 |
|
| 1312 |
return hidden
|
| 1313 |
|
|
|
|
| 166 |
'rope_base': self.kv.get(f'{arch}.rope.freq_base', 10000.0),
|
| 167 |
'swa_window': self.kv.get(f'{arch}.attention.sliding_window', 0),
|
| 168 |
'head_dim': head_dim,
|
| 169 |
+
'expert_count': self.kv.get(f'{arch}.expert_count', 0),
|
| 170 |
+
'expert_used_count': self.kv.get(f'{arch}.expert_used_count', 0),
|
| 171 |
}
|
| 172 |
|
| 173 |
def get_tensor_f32(self, name):
|
|
|
|
| 645 |
imp_fu_p, cnt_fu_p = make_imp(f'{pfx}.ffn_up.weight', n_embd if ffn_up_w is not None else 0)
|
| 646 |
imp_fd_p, cnt_fd_p = make_imp(f'{pfx}.ffn_down.weight', ffn_d if ffn_down_w is not None else 0)
|
| 647 |
|
| 648 |
+
# Call C function — entire layer in one call (FFN part will be NULL if MoE)
|
| 649 |
lib.hexstate_forward_layer(
|
| 650 |
h_ptr,
|
| 651 |
norm_p,
|
|
|
|
| 671 |
ctypes.c_int64(n_head), ctypes.c_int64(n_head_kv),
|
| 672 |
ctypes.c_int64(head_dim), ctypes.c_float(eps))
|
| 673 |
|
| 674 |
+
# Read back importance for the tensors that WERE processed in C
|
| 675 |
for name, arr, cnt in imp_refs:
|
| 676 |
self.importance[name] = (arr.astype(np.float64), cnt.value)
|
| 677 |
|
| 678 |
+
# Handle MoE FFN if C code skipped it
|
| 679 |
+
if ffn_gate_w is None:
|
| 680 |
+
# Re-normalize for FFN
|
| 681 |
+
normed_ff = self._hpc_rms_norm(hidden, ffn_norm_w, eps)
|
| 682 |
+
hidden = self._forward_moe_ffn(hidden, normed_ff, pfx)
|
| 683 |
+
|
| 684 |
# Force-free per-layer weight buffers (~1.4 GB) before next layer
|
| 685 |
del refs, imp_refs
|
| 686 |
import gc; gc.collect()
|
| 687 |
|
| 688 |
return hidden
|
| 689 |
|
| 690 |
+
def _forward_moe_ffn(self, hidden, normed_ff, pfx):
|
| 691 |
+
"""Python-side MoE FFN handling (supports packed and shared experts)."""
|
| 692 |
+
gate_inp_w = self._get_weight(f'{pfx}.ffn_gate_inp.weight')
|
| 693 |
+
if gate_inp_w is None:
|
| 694 |
+
return hidden
|
| 695 |
+
|
| 696 |
+
self._record(f'{pfx}.ffn_gate_inp.weight', normed_ff)
|
| 697 |
+
router_logits = normed_ff @ gate_inp_w.T
|
| 698 |
+
n_experts = router_logits.shape[-1]
|
| 699 |
+
probs = softmax(router_logits, axis=-1)
|
| 700 |
+
topk = self.cfg.get('expert_used_count', 2)
|
| 701 |
+
top_k_indices = np.argsort(probs, axis=-1)[:, -topk:]
|
| 702 |
+
|
| 703 |
+
ff_out = np.zeros_like(normed_ff)
|
| 704 |
+
|
| 705 |
+
# Check for packed experts (Qwen style)
|
| 706 |
+
p_gate = self._get_weight(f'{pfx}.ffn_gate_exps.weight')
|
| 707 |
+
p_up = self._get_weight(f'{pfx}.ffn_up_exps.weight')
|
| 708 |
+
p_down = self._get_weight(f'{pfx}.ffn_down_exps.weight')
|
| 709 |
+
|
| 710 |
+
for exp_id in range(n_experts):
|
| 711 |
+
if p_gate is not None:
|
| 712 |
+
ew_gate = p_gate[exp_id]
|
| 713 |
+
ew_up = p_up[exp_id]
|
| 714 |
+
ew_down = p_down[exp_id]
|
| 715 |
+
else:
|
| 716 |
+
ew_gate = self._get_weight(f'{pfx}.ffn_gate.{exp_id}.weight')
|
| 717 |
+
ew_up = self._get_weight(f'{pfx}.ffn_up.{exp_id}.weight')
|
| 718 |
+
ew_down = self._get_weight(f'{pfx}.ffn_down.{exp_id}.weight')
|
| 719 |
+
|
| 720 |
+
if ew_gate is None: continue
|
| 721 |
+
|
| 722 |
+
mask_exp = np.any(top_k_indices == exp_id, axis=-1)
|
| 723 |
+
if not np.any(mask_exp): continue
|
| 724 |
+
|
| 725 |
+
exp_input = normed_ff[mask_exp]
|
| 726 |
+
|
| 727 |
+
# Record importance
|
| 728 |
+
if p_gate is not None:
|
| 729 |
+
self._record(f'{pfx}.ffn_gate_exps.weight', exp_input)
|
| 730 |
+
self._record(f'{pfx}.ffn_up_exps.weight', exp_input)
|
| 731 |
+
else:
|
| 732 |
+
self._record(f'{pfx}.ffn_gate.{exp_id}.weight', exp_input)
|
| 733 |
+
self._record(f'{pfx}.ffn_up.{exp_id}.weight', exp_input)
|
| 734 |
+
|
| 735 |
+
g = self.act_fn(exp_input @ ew_gate.T)
|
| 736 |
+
u = exp_input @ ew_up.T
|
| 737 |
+
mid = g * u
|
| 738 |
+
|
| 739 |
+
if p_gate is not None:
|
| 740 |
+
self._record(f'{pfx}.ffn_down_exps.weight', mid)
|
| 741 |
+
else:
|
| 742 |
+
self._record(f'{pfx}.ffn_down.{exp_id}.weight', mid)
|
| 743 |
+
|
| 744 |
+
exp_out = mid @ ew_down.T
|
| 745 |
+
indices = np.where(mask_exp)[0]
|
| 746 |
+
for i, tidx in enumerate(indices):
|
| 747 |
+
w = probs[tidx, exp_id]
|
| 748 |
+
ff_out[tidx] += w * exp_out[i]
|
| 749 |
+
|
| 750 |
+
# Shared experts (Qwen style)
|
| 751 |
+
sh_gate = self._get_weight(f'{pfx}.ffn_gate_shexp.weight')
|
| 752 |
+
if sh_gate is not None:
|
| 753 |
+
sh_up = self._get_weight(f'{pfx}.ffn_up_shexp.weight')
|
| 754 |
+
sh_down = self._get_weight(f'{pfx}.ffn_down_shexp.weight')
|
| 755 |
+
self._record(f'{pfx}.ffn_gate_shexp.weight', normed_ff)
|
| 756 |
+
self._record(f'{pfx}.ffn_up_shexp.weight', normed_ff)
|
| 757 |
+
g = self.act_fn(normed_ff @ sh_gate.T)
|
| 758 |
+
u = normed_ff @ sh_up.T
|
| 759 |
+
mid = g * u
|
| 760 |
+
self._record(f'{pfx}.ffn_down_shexp.weight', mid)
|
| 761 |
+
ff_out += mid @ sh_down.T
|
| 762 |
+
|
| 763 |
+
return hidden + ff_out
|
| 764 |
+
|
| 765 |
def _hpc_rms_norm(self, x, weight, eps):
|
| 766 |
"""RMS norm via HPC C library, falling back to numpy."""
|
| 767 |
if self._hpc_lib and x.flags['C_CONTIGUOUS']:
|
|
|
|
| 1138 |
hidden = hidden + ff_out
|
| 1139 |
else:
|
| 1140 |
# MoE path
|
| 1141 |
+
hidden = self._forward_moe_ffn(hidden, normed_ff, pfx)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1142 |
|
| 1143 |
return hidden
|
| 1144 |
|
|
|
|
| 1214 |
self._record(f'{pfx}.ffn_down.weight', ff_mid)
|
| 1215 |
ff_out = ff_mid @ down_w.T
|
| 1216 |
hidden = hidden + ff_out
|
| 1217 |
+
else:
|
| 1218 |
+
hidden = self._forward_moe_ffn(hidden, normed_ff, pfx)
|
| 1219 |
|
| 1220 |
return hidden
|
| 1221 |
|
|
|
|
| 1357 |
self._record(f'{pfx}.ffn_down.weight', ff_mid)
|
| 1358 |
ff_out = ff_mid @ down_w.T
|
| 1359 |
hidden = hidden + ff_out
|
| 1360 |
+
else:
|
| 1361 |
+
hidden = self._forward_moe_ffn(hidden, normed_ff, pfx)
|
| 1362 |
|
| 1363 |
return hidden
|
| 1364 |
|
hexstate_quantize.c
CHANGED
|
@@ -4252,16 +4252,16 @@ static void hpc_read_importance(HPCGraph *g, const float *x, int64_t dim,
|
|
| 4252 |
*/
|
| 4253 |
static void hpc_matmul_graph(const float *x, const float *weight, float *out,
|
| 4254 |
float *importance, int64_t *count,
|
| 4255 |
-
int64_t M, int64_t K, int64_t N)
|
| 4256 |
{
|
| 4257 |
/* Build HPCGraph over input columns for importance */
|
| 4258 |
int64_t stride = (K > 512) ? K / 512 : 1;
|
| 4259 |
int64_t n_sites = (K + stride - 1) / stride;
|
| 4260 |
HPCGraph *g = hpc_create(n_sites);
|
|
|
|
| 4261 |
|
| 4262 |
-
if (g &&
|
| 4263 |
/* Compute per-column energies */
|
| 4264 |
-
float *col_energy = (float *)calloc(K, sizeof(float));
|
| 4265 |
#pragma omp parallel for schedule(static)
|
| 4266 |
for (int64_t j = 0; j < K; j++) {
|
| 4267 |
float s = 0.0f;
|
|
@@ -4307,28 +4307,37 @@ static void hpc_matmul_graph(const float *x, const float *weight, float *out,
|
|
| 4307 |
importance[j] += col_energy[j] * (float)boost;
|
| 4308 |
}
|
| 4309 |
if (count) *count += M;
|
| 4310 |
-
|
| 4311 |
-
free(col_energy);
|
| 4312 |
-
hpc_destroy(g);
|
| 4313 |
}
|
| 4314 |
|
| 4315 |
-
/* Matmul: out = x @ W.T
|
| 4316 |
#pragma omp parallel for schedule(static)
|
| 4317 |
for (int64_t i = 0; i < M; i++) {
|
| 4318 |
const float *xi = x + i * K;
|
| 4319 |
float *oi = out + i * N;
|
| 4320 |
-
|
| 4321 |
-
|
| 4322 |
-
|
| 4323 |
-
|
| 4324 |
-
|
| 4325 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4326 |
}
|
| 4327 |
}
|
|
|
|
|
|
|
|
|
|
| 4328 |
}
|
| 4329 |
|
| 4330 |
/* ── Helper: RMS norm (OpenMP) ── */
|
| 4331 |
-
|
| 4332 |
int64_t seq, int64_t dim, float eps)
|
| 4333 |
{
|
| 4334 |
#pragma omp parallel for schedule(static)
|
|
@@ -4408,7 +4417,7 @@ void hexstate_forward_layer(
|
|
| 4408 |
if (!normed) return;
|
| 4409 |
|
| 4410 |
/* ══════════════ Phase 1: Attention Norm ══════════════ */
|
| 4411 |
-
|
| 4412 |
|
| 4413 |
/* ══════════════ Phase 2: QKV Projection via HPC Graph ══════════════ */
|
| 4414 |
float *attn_out = (float *)calloc(seq_len * n_embd, sizeof(float));
|
|
@@ -4421,7 +4430,7 @@ void hexstate_forward_layer(
|
|
| 4421 |
|
| 4422 |
/* Graph-based matmul: importance via HPCGraph marginals */
|
| 4423 |
hpc_matmul_graph(normed, qkv_w, qkv, imp_qkv, cnt_qkv,
|
| 4424 |
-
seq_len, n_embd, qkv_dim);
|
| 4425 |
|
| 4426 |
/* Split Q, K, V */
|
| 4427 |
int64_t q_total = n_head * head_dim;
|
|
@@ -4444,8 +4453,10 @@ void hexstate_forward_layer(
|
|
| 4444 |
HPCGraph *attn_graph = hpc_create(n_head);
|
| 4445 |
float *S = (float *)calloc(n_head * head_dim * head_dim, sizeof(float));
|
| 4446 |
float *z_acc = (float *)calloc(n_head * head_dim, sizeof(float));
|
|
|
|
|
|
|
| 4447 |
|
| 4448 |
-
if (attn_graph && S && z_acc) {
|
| 4449 |
for (int64_t t = 0; t < seq_len; t++) {
|
| 4450 |
/* Extract Q/K/V for this timestep (handle strided layout) */
|
| 4451 |
float *qt_base = qkv + t * qkv_dim;
|
|
@@ -4519,15 +4530,14 @@ void hexstate_forward_layer(
|
|
| 4519 |
den += qf[d] * zh[d];
|
| 4520 |
float inv_den = 1.0f / den;
|
| 4521 |
|
| 4522 |
-
/* Write to
|
| 4523 |
-
float *ao =
|
| 4524 |
for (int64_t d2 = 0; d2 < head_dim; d2++) {
|
| 4525 |
float num = 0.0f;
|
| 4526 |
for (int64_t d1 = 0; d1 < head_dim; d1++)
|
| 4527 |
num += qf[d1] * Sh[d1 * head_dim + d2];
|
| 4528 |
-
/* Accumulate into
|
| 4529 |
-
|
| 4530 |
-
ao[h * head_dim + d2] = num * inv_den;
|
| 4531 |
}
|
| 4532 |
}
|
| 4533 |
|
|
@@ -4539,25 +4549,25 @@ void hexstate_forward_layer(
|
|
| 4539 |
|
| 4540 |
/* Gate projection if present */
|
| 4541 |
if (gate_w && gate_rows > 0) {
|
| 4542 |
-
|
| 4543 |
-
|
| 4544 |
-
float *gated = (float *)malloc(seq_len *
|
| 4545 |
if (gated) {
|
| 4546 |
-
hpc_matmul_graph(
|
| 4547 |
-
seq_len,
|
| 4548 |
-
|
| 4549 |
-
|
| 4550 |
-
|
| 4551 |
-
#pragma omp parallel for schedule(static)
|
| 4552 |
-
for (int64_t i = 0; i < seq_len; i++) {
|
| 4553 |
-
memcpy(attn_out + i * n_embd, gated + i * gate_rows, copy_dim * sizeof(float));
|
| 4554 |
-
if (copy_dim < n_embd) {
|
| 4555 |
-
memset(attn_out + i * n_embd + copy_dim, 0, (n_embd - copy_dim) * sizeof(float));
|
| 4556 |
-
}
|
| 4557 |
}
|
| 4558 |
free(gated);
|
| 4559 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4560 |
}
|
|
|
|
| 4561 |
|
| 4562 |
if (attn_graph) hpc_destroy(attn_graph);
|
| 4563 |
free(S); free(z_acc); free(qkv);
|
|
@@ -4568,23 +4578,25 @@ void hexstate_forward_layer(
|
|
| 4568 |
float *K_buf = (float *)malloc(seq_len * k_dim * sizeof(float));
|
| 4569 |
float *V_buf = (float *)malloc(seq_len * v_dim * sizeof(float));
|
| 4570 |
if (!Q || !K_buf || !V_buf) {
|
| 4571 |
-
free(Q); free(K_buf); free(V_buf);
|
| 4572 |
free(normed); free(attn_out);
|
| 4573 |
return;
|
| 4574 |
}
|
| 4575 |
|
| 4576 |
-
hpc_matmul_graph(normed, q_w, Q, imp_q, cnt_q, seq_len, n_embd, q_dim);
|
| 4577 |
-
hpc_matmul_graph(normed, k_w, K_buf, imp_k, cnt_k, seq_len, n_embd, k_dim);
|
| 4578 |
-
hpc_matmul_graph(normed, v_w, V_buf, imp_v, cnt_v, seq_len, n_embd, v_dim);
|
| 4579 |
|
| 4580 |
/* Same HPC attention as above but with separate Q/K/V buffers */
|
| 4581 |
int64_t hd_q = q_dim / n_head;
|
| 4582 |
int64_t hd_kv = k_dim / n_head_kv;
|
|
|
|
| 4583 |
HPCGraph *attn_graph = hpc_create(n_head);
|
| 4584 |
float *S = (float *)calloc(n_head * hd_kv * hd_kv, sizeof(float));
|
| 4585 |
float *z_acc = (float *)calloc(n_head * hd_kv, sizeof(float));
|
|
|
|
| 4586 |
|
| 4587 |
-
if (attn_graph && S && z_acc) {
|
| 4588 |
for (int64_t t = 0; t < seq_len; t++) {
|
| 4589 |
/* Encode heads into graph */
|
| 4590 |
for (int64_t h = 0; h < n_head; h++) {
|
|
@@ -4635,15 +4647,14 @@ void hexstate_forward_layer(
|
|
| 4635 |
den += qf * zh[d];
|
| 4636 |
}
|
| 4637 |
float inv_den = 1.0f / den;
|
| 4638 |
-
float *ao =
|
| 4639 |
for (int64_t d2 = 0; d2 < hd_kv; d2++) {
|
| 4640 |
float num = 0.0f;
|
| 4641 |
for (int64_t d1 = 0; d1 < feat; d1++) {
|
| 4642 |
float qf = (qh[d1] > 0 ? qh[d1] : 0) + 1e-6f;
|
| 4643 |
num += qf * Sh[d1*hd_kv+d2];
|
| 4644 |
}
|
| 4645 |
-
|
| 4646 |
-
ao[h*hd_kv+d2] = num * inv_den;
|
| 4647 |
}
|
| 4648 |
}
|
| 4649 |
if (t > 0 && t % 64 == 0)
|
|
@@ -4653,16 +4664,36 @@ void hexstate_forward_layer(
|
|
| 4653 |
|
| 4654 |
/* Output projection */
|
| 4655 |
if (o_w && o_cols > 0) {
|
| 4656 |
-
|
| 4657 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4658 |
float *projected = (float *)calloc(seq_len * n_embd, sizeof(float));
|
| 4659 |
if (projected) {
|
| 4660 |
-
hpc_matmul_graph(
|
| 4661 |
-
seq_len, o_cols, n_embd);
|
| 4662 |
memcpy(attn_out, projected, seq_len * n_embd * sizeof(float));
|
| 4663 |
free(projected);
|
| 4664 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4665 |
}
|
|
|
|
| 4666 |
|
| 4667 |
if (attn_graph) hpc_destroy(attn_graph);
|
| 4668 |
free(S); free(z_acc);
|
|
@@ -4682,13 +4713,13 @@ void hexstate_forward_layer(
|
|
| 4682 |
float *up_out = (float *)malloc(seq_len * ffn_dim * sizeof(float));
|
| 4683 |
|
| 4684 |
if (normed_ff && gate_out && up_out) {
|
| 4685 |
-
|
| 4686 |
|
| 4687 |
/* Graph-based matmul for FFN with importance */
|
| 4688 |
hpc_matmul_graph(normed_ff, ffn_gate_w, gate_out,
|
| 4689 |
-
imp_ffn_gate, cnt_ffn_gate, seq_len, n_embd, ffn_dim);
|
| 4690 |
hpc_matmul_graph(normed_ff, ffn_up_w, up_out,
|
| 4691 |
-
imp_ffn_up, cnt_ffn_up, seq_len, n_embd, ffn_dim);
|
| 4692 |
|
| 4693 |
/* SiLU(gate) * up */
|
| 4694 |
hpc_silu(gate_out, seq_len * ffn_dim);
|
|
@@ -4697,16 +4728,16 @@ void hexstate_forward_layer(
|
|
| 4697 |
gate_out[i] *= up_out[i];
|
| 4698 |
|
| 4699 |
/* Down projection: graph-based importance recording */
|
| 4700 |
-
float *
|
| 4701 |
-
if (
|
| 4702 |
-
hpc_matmul_graph(gate_out, ffn_down_w,
|
| 4703 |
imp_ffn_down, cnt_ffn_down,
|
| 4704 |
-
seq_len, ffn_dim, n_embd);
|
| 4705 |
/* Residual add */
|
| 4706 |
#pragma omp parallel for schedule(static)
|
| 4707 |
for (int64_t i = 0; i < total; i++)
|
| 4708 |
-
hidden[i] +=
|
| 4709 |
-
free(
|
| 4710 |
}
|
| 4711 |
}
|
| 4712 |
|
|
@@ -4717,6 +4748,7 @@ void hexstate_forward_layer(
|
|
| 4717 |
free(attn_out);
|
| 4718 |
}
|
| 4719 |
|
|
|
|
| 4720 |
#ifndef HEXSTATE_LIBRARY
|
| 4721 |
/* ═══════════════════════════════════════════════════════════════════════════
|
| 4722 |
* MAIN
|
|
|
|
| 4252 |
*/
|
| 4253 |
static void hpc_matmul_graph(const float *x, const float *weight, float *out,
|
| 4254 |
float *importance, int64_t *count,
|
| 4255 |
+
int64_t M, int64_t K, int64_t N, int trans_w)
|
| 4256 |
{
|
| 4257 |
/* Build HPCGraph over input columns for importance */
|
| 4258 |
int64_t stride = (K > 512) ? K / 512 : 1;
|
| 4259 |
int64_t n_sites = (K + stride - 1) / stride;
|
| 4260 |
HPCGraph *g = hpc_create(n_sites);
|
| 4261 |
+
float *col_energy = (float *)calloc(K, sizeof(float));
|
| 4262 |
|
| 4263 |
+
if (g && col_energy) {
|
| 4264 |
/* Compute per-column energies */
|
|
|
|
| 4265 |
#pragma omp parallel for schedule(static)
|
| 4266 |
for (int64_t j = 0; j < K; j++) {
|
| 4267 |
float s = 0.0f;
|
|
|
|
| 4307 |
importance[j] += col_energy[j] * (float)boost;
|
| 4308 |
}
|
| 4309 |
if (count) *count += M;
|
|
|
|
|
|
|
|
|
|
| 4310 |
}
|
| 4311 |
|
| 4312 |
+
/* Matmul: out = x @ W.T (trans_w=0) or x @ W (trans_w=1) */
|
| 4313 |
#pragma omp parallel for schedule(static)
|
| 4314 |
for (int64_t i = 0; i < M; i++) {
|
| 4315 |
const float *xi = x + i * K;
|
| 4316 |
float *oi = out + i * N;
|
| 4317 |
+
if (trans_w) {
|
| 4318 |
+
for (int64_t n = 0; n < N; n++) {
|
| 4319 |
+
float dot = 0.0f;
|
| 4320 |
+
for (int64_t k = 0; k < K; k++)
|
| 4321 |
+
dot += xi[k] * weight[k * N + n];
|
| 4322 |
+
oi[n] = dot;
|
| 4323 |
+
}
|
| 4324 |
+
} else {
|
| 4325 |
+
for (int64_t n = 0; n < N; n++) {
|
| 4326 |
+
const float *wn = weight + n * K;
|
| 4327 |
+
float dot = 0.0f;
|
| 4328 |
+
for (int64_t k = 0; k < K; k++)
|
| 4329 |
+
dot += xi[k] * wn[k];
|
| 4330 |
+
oi[n] = dot;
|
| 4331 |
+
}
|
| 4332 |
}
|
| 4333 |
}
|
| 4334 |
+
|
| 4335 |
+
if (col_energy) free(col_energy);
|
| 4336 |
+
if (g) hpc_destroy(g);
|
| 4337 |
}
|
| 4338 |
|
| 4339 |
/* ── Helper: RMS norm (OpenMP) ── */
|
| 4340 |
+
void hexstate_rms_norm(const float *x, const float *w, float *out,
|
| 4341 |
int64_t seq, int64_t dim, float eps)
|
| 4342 |
{
|
| 4343 |
#pragma omp parallel for schedule(static)
|
|
|
|
| 4417 |
if (!normed) return;
|
| 4418 |
|
| 4419 |
/* ══════════════ Phase 1: Attention Norm ══════════════ */
|
| 4420 |
+
hexstate_rms_norm(hidden, norm_w, normed, seq_len, n_embd, eps);
|
| 4421 |
|
| 4422 |
/* ══════════════ Phase 2: QKV Projection via HPC Graph ══════════════ */
|
| 4423 |
float *attn_out = (float *)calloc(seq_len * n_embd, sizeof(float));
|
|
|
|
| 4430 |
|
| 4431 |
/* Graph-based matmul: importance via HPCGraph marginals */
|
| 4432 |
hpc_matmul_graph(normed, qkv_w, qkv, imp_qkv, cnt_qkv,
|
| 4433 |
+
seq_len, n_embd, qkv_dim, 0);
|
| 4434 |
|
| 4435 |
/* Split Q, K, V */
|
| 4436 |
int64_t q_total = n_head * head_dim;
|
|
|
|
| 4453 |
HPCGraph *attn_graph = hpc_create(n_head);
|
| 4454 |
float *S = (float *)calloc(n_head * head_dim * head_dim, sizeof(float));
|
| 4455 |
float *z_acc = (float *)calloc(n_head * head_dim, sizeof(float));
|
| 4456 |
+
int64_t inner_dim = n_head * head_dim;
|
| 4457 |
+
float *attn_inner = (float *)calloc(seq_len * inner_dim, sizeof(float));
|
| 4458 |
|
| 4459 |
+
if (attn_graph && S && z_acc && attn_inner) {
|
| 4460 |
for (int64_t t = 0; t < seq_len; t++) {
|
| 4461 |
/* Extract Q/K/V for this timestep (handle strided layout) */
|
| 4462 |
float *qt_base = qkv + t * qkv_dim;
|
|
|
|
| 4530 |
den += qf[d] * zh[d];
|
| 4531 |
float inv_den = 1.0f / den;
|
| 4532 |
|
| 4533 |
+
/* Write to attn_inner at position [t, h*head_dim ... ] */
|
| 4534 |
+
float *ao = attn_inner + t * inner_dim;
|
| 4535 |
for (int64_t d2 = 0; d2 < head_dim; d2++) {
|
| 4536 |
float num = 0.0f;
|
| 4537 |
for (int64_t d1 = 0; d1 < head_dim; d1++)
|
| 4538 |
num += qf[d1] * Sh[d1 * head_dim + d2];
|
| 4539 |
+
/* Accumulate into attn_inner (multiple heads write here) */
|
| 4540 |
+
ao[h * head_dim + d2] = num * inv_den;
|
|
|
|
| 4541 |
}
|
| 4542 |
}
|
| 4543 |
|
|
|
|
| 4549 |
|
| 4550 |
/* Gate projection if present */
|
| 4551 |
if (gate_w && gate_rows > 0) {
|
| 4552 |
+
int trans_w = (gate_rows == inner_dim) ? 1 : 0;
|
| 4553 |
+
int64_t N_out = trans_w ? n_embd : gate_rows;
|
| 4554 |
+
float *gated = (float *)malloc(seq_len * N_out * sizeof(float));
|
| 4555 |
if (gated) {
|
| 4556 |
+
hpc_matmul_graph(attn_inner, gate_w, gated, imp_gate, cnt_gate,
|
| 4557 |
+
seq_len, inner_dim, N_out, trans_w);
|
| 4558 |
+
for (int64_t t = 0; t < seq_len; t++) {
|
| 4559 |
+
int64_t copy_dim = N_out < n_embd ? N_out : n_embd;
|
| 4560 |
+
memcpy(attn_out + t * n_embd, gated + t * N_out, copy_dim * sizeof(float));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4561 |
}
|
| 4562 |
free(gated);
|
| 4563 |
}
|
| 4564 |
+
} else {
|
| 4565 |
+
for (int64_t t = 0; t < seq_len; t++) {
|
| 4566 |
+
int64_t copy_dim = inner_dim < n_embd ? inner_dim : n_embd;
|
| 4567 |
+
memcpy(attn_out + t * n_embd, attn_inner + t * inner_dim, copy_dim * sizeof(float));
|
| 4568 |
+
}
|
| 4569 |
}
|
| 4570 |
+
if (attn_inner) free(attn_inner);
|
| 4571 |
|
| 4572 |
if (attn_graph) hpc_destroy(attn_graph);
|
| 4573 |
free(S); free(z_acc); free(qkv);
|
|
|
|
| 4578 |
float *K_buf = (float *)malloc(seq_len * k_dim * sizeof(float));
|
| 4579 |
float *V_buf = (float *)malloc(seq_len * v_dim * sizeof(float));
|
| 4580 |
if (!Q || !K_buf || !V_buf) {
|
| 4581 |
+
if(Q) free(Q); if(K_buf) free(K_buf); if(V_buf) free(V_buf);
|
| 4582 |
free(normed); free(attn_out);
|
| 4583 |
return;
|
| 4584 |
}
|
| 4585 |
|
| 4586 |
+
hpc_matmul_graph(normed, q_w, Q, imp_q, cnt_q, seq_len, n_embd, q_dim, 0);
|
| 4587 |
+
hpc_matmul_graph(normed, k_w, K_buf, imp_k, cnt_k, seq_len, n_embd, k_dim, 0);
|
| 4588 |
+
hpc_matmul_graph(normed, v_w, V_buf, imp_v, cnt_v, seq_len, n_embd, v_dim, 0);
|
| 4589 |
|
| 4590 |
/* Same HPC attention as above but with separate Q/K/V buffers */
|
| 4591 |
int64_t hd_q = q_dim / n_head;
|
| 4592 |
int64_t hd_kv = k_dim / n_head_kv;
|
| 4593 |
+
int64_t inner_dim = n_head * hd_kv;
|
| 4594 |
HPCGraph *attn_graph = hpc_create(n_head);
|
| 4595 |
float *S = (float *)calloc(n_head * hd_kv * hd_kv, sizeof(float));
|
| 4596 |
float *z_acc = (float *)calloc(n_head * hd_kv, sizeof(float));
|
| 4597 |
+
float *attn_inner = (float *)calloc(seq_len * inner_dim, sizeof(float));
|
| 4598 |
|
| 4599 |
+
if (attn_graph && S && z_acc && attn_inner) {
|
| 4600 |
for (int64_t t = 0; t < seq_len; t++) {
|
| 4601 |
/* Encode heads into graph */
|
| 4602 |
for (int64_t h = 0; h < n_head; h++) {
|
|
|
|
| 4647 |
den += qf * zh[d];
|
| 4648 |
}
|
| 4649 |
float inv_den = 1.0f / den;
|
| 4650 |
+
float *ao = attn_inner + t * inner_dim;
|
| 4651 |
for (int64_t d2 = 0; d2 < hd_kv; d2++) {
|
| 4652 |
float num = 0.0f;
|
| 4653 |
for (int64_t d1 = 0; d1 < feat; d1++) {
|
| 4654 |
float qf = (qh[d1] > 0 ? qh[d1] : 0) + 1e-6f;
|
| 4655 |
num += qf * Sh[d1*hd_kv+d2];
|
| 4656 |
}
|
| 4657 |
+
ao[h*hd_kv+d2] = num * inv_den;
|
|
|
|
| 4658 |
}
|
| 4659 |
}
|
| 4660 |
if (t > 0 && t % 64 == 0)
|
|
|
|
| 4664 |
|
| 4665 |
/* Output projection */
|
| 4666 |
if (o_w && o_cols > 0) {
|
| 4667 |
+
float *proj_in = attn_inner;
|
| 4668 |
+
int free_proj_in = 0;
|
| 4669 |
+
if (inner_dim != o_cols) {
|
| 4670 |
+
proj_in = (float *)calloc(seq_len * o_cols, sizeof(float));
|
| 4671 |
+
if (proj_in) {
|
| 4672 |
+
for (int64_t t = 0; t < seq_len; t++) {
|
| 4673 |
+
int64_t copy_dim = inner_dim < o_cols ? inner_dim : o_cols;
|
| 4674 |
+
memcpy(proj_in + t * o_cols, attn_inner + t * inner_dim, copy_dim * sizeof(float));
|
| 4675 |
+
}
|
| 4676 |
+
free_proj_in = 1;
|
| 4677 |
+
} else {
|
| 4678 |
+
proj_in = attn_inner;
|
| 4679 |
+
}
|
| 4680 |
+
}
|
| 4681 |
+
|
| 4682 |
float *projected = (float *)calloc(seq_len * n_embd, sizeof(float));
|
| 4683 |
if (projected) {
|
| 4684 |
+
hpc_matmul_graph(proj_in, o_w, projected, imp_o, cnt_o,
|
| 4685 |
+
seq_len, o_cols, n_embd, 0);
|
| 4686 |
memcpy(attn_out, projected, seq_len * n_embd * sizeof(float));
|
| 4687 |
free(projected);
|
| 4688 |
}
|
| 4689 |
+
if (free_proj_in && proj_in != attn_inner) free(proj_in);
|
| 4690 |
+
} else {
|
| 4691 |
+
for (int64_t t = 0; t < seq_len; t++) {
|
| 4692 |
+
int64_t copy_dim = inner_dim < n_embd ? inner_dim : n_embd;
|
| 4693 |
+
memcpy(attn_out + t * n_embd, attn_inner + t * inner_dim, copy_dim * sizeof(float));
|
| 4694 |
+
}
|
| 4695 |
}
|
| 4696 |
+
if (attn_inner) free(attn_inner);
|
| 4697 |
|
| 4698 |
if (attn_graph) hpc_destroy(attn_graph);
|
| 4699 |
free(S); free(z_acc);
|
|
|
|
| 4713 |
float *up_out = (float *)malloc(seq_len * ffn_dim * sizeof(float));
|
| 4714 |
|
| 4715 |
if (normed_ff && gate_out && up_out) {
|
| 4716 |
+
hexstate_rms_norm(hidden, ffn_norm_w, normed_ff, seq_len, n_embd, eps);
|
| 4717 |
|
| 4718 |
/* Graph-based matmul for FFN with importance */
|
| 4719 |
hpc_matmul_graph(normed_ff, ffn_gate_w, gate_out,
|
| 4720 |
+
imp_ffn_gate, cnt_ffn_gate, seq_len, n_embd, ffn_dim, 0);
|
| 4721 |
hpc_matmul_graph(normed_ff, ffn_up_w, up_out,
|
| 4722 |
+
imp_ffn_up, cnt_ffn_up, seq_len, n_embd, ffn_dim, 0);
|
| 4723 |
|
| 4724 |
/* SiLU(gate) * up */
|
| 4725 |
hpc_silu(gate_out, seq_len * ffn_dim);
|
|
|
|
| 4728 |
gate_out[i] *= up_out[i];
|
| 4729 |
|
| 4730 |
/* Down projection: graph-based importance recording */
|
| 4731 |
+
float *ff_out_buf = (float *)malloc(seq_len * n_embd * sizeof(float));
|
| 4732 |
+
if (ff_out_buf) {
|
| 4733 |
+
hpc_matmul_graph(gate_out, ffn_down_w, ff_out_buf,
|
| 4734 |
imp_ffn_down, cnt_ffn_down,
|
| 4735 |
+
seq_len, ffn_dim, n_embd, 0);
|
| 4736 |
/* Residual add */
|
| 4737 |
#pragma omp parallel for schedule(static)
|
| 4738 |
for (int64_t i = 0; i < total; i++)
|
| 4739 |
+
hidden[i] += ff_out_buf[i];
|
| 4740 |
+
free(ff_out_buf);
|
| 4741 |
}
|
| 4742 |
}
|
| 4743 |
|
|
|
|
| 4748 |
free(attn_out);
|
| 4749 |
}
|
| 4750 |
|
| 4751 |
+
|
| 4752 |
#ifndef HEXSTATE_LIBRARY
|
| 4753 |
/* ═══════════════════════════════════════════════════════════════════════════
|
| 4754 |
* MAIN
|
hpc_forward_merged.c
CHANGED
|
@@ -75,16 +75,16 @@ static void hpc_read_importance(HPCGraph *g, const float *x, int64_t dim,
|
|
| 75 |
*/
|
| 76 |
static void hpc_matmul_graph(const float *x, const float *weight, float *out,
|
| 77 |
float *importance, int64_t *count,
|
| 78 |
-
int64_t M, int64_t K, int64_t N)
|
| 79 |
{
|
| 80 |
/* Build HPCGraph over input columns for importance */
|
| 81 |
int64_t stride = (K > 512) ? K / 512 : 1;
|
| 82 |
int64_t n_sites = (K + stride - 1) / stride;
|
| 83 |
HPCGraph *g = hpc_create(n_sites);
|
|
|
|
| 84 |
|
| 85 |
-
if (g &&
|
| 86 |
/* Compute per-column energies */
|
| 87 |
-
float *col_energy = (float *)calloc(K, sizeof(float));
|
| 88 |
#pragma omp parallel for schedule(static)
|
| 89 |
for (int64_t j = 0; j < K; j++) {
|
| 90 |
float s = 0.0f;
|
|
@@ -130,24 +130,33 @@ static void hpc_matmul_graph(const float *x, const float *weight, float *out,
|
|
| 130 |
importance[j] += col_energy[j] * (float)boost;
|
| 131 |
}
|
| 132 |
if (count) *count += M;
|
| 133 |
-
|
| 134 |
-
free(col_energy);
|
| 135 |
-
hpc_destroy(g);
|
| 136 |
}
|
| 137 |
|
| 138 |
-
/* Matmul: out = x @ W.T
|
| 139 |
#pragma omp parallel for schedule(static)
|
| 140 |
for (int64_t i = 0; i < M; i++) {
|
| 141 |
const float *xi = x + i * K;
|
| 142 |
float *oi = out + i * N;
|
| 143 |
-
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 149 |
}
|
| 150 |
}
|
|
|
|
|
|
|
|
|
|
| 151 |
}
|
| 152 |
|
| 153 |
/* ── Helper: RMS norm (OpenMP) ── */
|
|
@@ -243,8 +252,8 @@ void hexstate_forward_layer(
|
|
| 243 |
if (!qkv) { free(normed); free(attn_out); return; }
|
| 244 |
|
| 245 |
/* Graph-based matmul: importance via HPCGraph marginals */
|
| 246 |
-
hpc_matmul_graph(normed, qkv_w, qkv, imp_qkv, cnt_qkv,
|
| 247 |
-
seq_len, n_embd, qkv_dim);
|
| 248 |
|
| 249 |
/* Split Q, K, V */
|
| 250 |
int64_t q_total = n_head * head_dim;
|
|
@@ -363,14 +372,15 @@ void hexstate_forward_layer(
|
|
| 363 |
|
| 364 |
/* Gate projection if present */
|
| 365 |
if (gate_w && gate_rows > 0) {
|
| 366 |
-
|
| 367 |
-
|
|
|
|
| 368 |
if (gated) {
|
| 369 |
-
hpc_matmul_graph(attn_inner, gate_w, gated, imp_gate, cnt_gate,
|
| 370 |
-
seq_len, inner_dim,
|
| 371 |
for (int64_t t = 0; t < seq_len; t++) {
|
| 372 |
-
int64_t copy_dim =
|
| 373 |
-
memcpy(attn_out + t * n_embd, gated + t *
|
| 374 |
}
|
| 375 |
free(gated);
|
| 376 |
}
|
|
@@ -391,14 +401,14 @@ void hexstate_forward_layer(
|
|
| 391 |
float *K_buf = (float *)malloc(seq_len * k_dim * sizeof(float));
|
| 392 |
float *V_buf = (float *)malloc(seq_len * v_dim * sizeof(float));
|
| 393 |
if (!Q || !K_buf || !V_buf) {
|
| 394 |
-
free(Q); free(K_buf); free(V_buf);
|
| 395 |
free(normed); free(attn_out);
|
| 396 |
return;
|
| 397 |
}
|
| 398 |
|
| 399 |
-
hpc_matmul_graph(normed, q_w, Q, imp_q, cnt_q, seq_len, n_embd, q_dim);
|
| 400 |
-
hpc_matmul_graph(normed, k_w, K_buf, imp_k, cnt_k, seq_len, n_embd, k_dim);
|
| 401 |
-
hpc_matmul_graph(normed, v_w, V_buf, imp_v, cnt_v, seq_len, n_embd, v_dim);
|
| 402 |
|
| 403 |
/* Same HPC attention as above but with separate Q/K/V buffers */
|
| 404 |
int64_t hd_q = q_dim / n_head;
|
|
@@ -495,7 +505,7 @@ void hexstate_forward_layer(
|
|
| 495 |
float *projected = (float *)calloc(seq_len * n_embd, sizeof(float));
|
| 496 |
if (projected) {
|
| 497 |
hpc_matmul_graph(proj_in, o_w, projected, imp_o, cnt_o,
|
| 498 |
-
seq_len, o_cols, n_embd);
|
| 499 |
memcpy(attn_out, projected, seq_len * n_embd * sizeof(float));
|
| 500 |
free(projected);
|
| 501 |
}
|
|
@@ -530,9 +540,9 @@ void hexstate_forward_layer(
|
|
| 530 |
|
| 531 |
/* Graph-based matmul for FFN with importance */
|
| 532 |
hpc_matmul_graph(normed_ff, ffn_gate_w, gate_out,
|
| 533 |
-
imp_ffn_gate, cnt_ffn_gate, seq_len, n_embd, ffn_dim);
|
| 534 |
hpc_matmul_graph(normed_ff, ffn_up_w, up_out,
|
| 535 |
-
imp_ffn_up, cnt_ffn_up, seq_len, n_embd, ffn_dim);
|
| 536 |
|
| 537 |
/* SiLU(gate) * up */
|
| 538 |
hpc_silu(gate_out, seq_len * ffn_dim);
|
|
@@ -541,16 +551,16 @@ void hexstate_forward_layer(
|
|
| 541 |
gate_out[i] *= up_out[i];
|
| 542 |
|
| 543 |
/* Down projection: graph-based importance recording */
|
| 544 |
-
float *
|
| 545 |
-
if (
|
| 546 |
-
hpc_matmul_graph(gate_out, ffn_down_w,
|
| 547 |
imp_ffn_down, cnt_ffn_down,
|
| 548 |
-
seq_len, ffn_dim, n_embd);
|
| 549 |
/* Residual add */
|
| 550 |
#pragma omp parallel for schedule(static)
|
| 551 |
for (int64_t i = 0; i < total; i++)
|
| 552 |
-
hidden[i] +=
|
| 553 |
-
free(
|
| 554 |
}
|
| 555 |
}
|
| 556 |
|
|
|
|
| 75 |
*/
|
| 76 |
static void hpc_matmul_graph(const float *x, const float *weight, float *out,
|
| 77 |
float *importance, int64_t *count,
|
| 78 |
+
int64_t M, int64_t K, int64_t N, int trans_w)
|
| 79 |
{
|
| 80 |
/* Build HPCGraph over input columns for importance */
|
| 81 |
int64_t stride = (K > 512) ? K / 512 : 1;
|
| 82 |
int64_t n_sites = (K + stride - 1) / stride;
|
| 83 |
HPCGraph *g = hpc_create(n_sites);
|
| 84 |
+
float *col_energy = (float *)calloc(K, sizeof(float));
|
| 85 |
|
| 86 |
+
if (g && col_energy) {
|
| 87 |
/* Compute per-column energies */
|
|
|
|
| 88 |
#pragma omp parallel for schedule(static)
|
| 89 |
for (int64_t j = 0; j < K; j++) {
|
| 90 |
float s = 0.0f;
|
|
|
|
| 130 |
importance[j] += col_energy[j] * (float)boost;
|
| 131 |
}
|
| 132 |
if (count) *count += M;
|
|
|
|
|
|
|
|
|
|
| 133 |
}
|
| 134 |
|
| 135 |
+
/* Matmul: out = x @ W.T (trans_w=0) or x @ W (trans_w=1) */
|
| 136 |
#pragma omp parallel for schedule(static)
|
| 137 |
for (int64_t i = 0; i < M; i++) {
|
| 138 |
const float *xi = x + i * K;
|
| 139 |
float *oi = out + i * N;
|
| 140 |
+
if (trans_w) {
|
| 141 |
+
for (int64_t n = 0; n < N; n++) {
|
| 142 |
+
float dot = 0.0f;
|
| 143 |
+
for (int64_t k = 0; k < K; k++)
|
| 144 |
+
dot += xi[k] * weight[k * N + n];
|
| 145 |
+
oi[n] = dot;
|
| 146 |
+
}
|
| 147 |
+
} else {
|
| 148 |
+
for (int64_t n = 0; n < N; n++) {
|
| 149 |
+
const float *wn = weight + n * K;
|
| 150 |
+
float dot = 0.0f;
|
| 151 |
+
for (int64_t k = 0; k < K; k++)
|
| 152 |
+
dot += xi[k] * wn[k];
|
| 153 |
+
oi[n] = dot;
|
| 154 |
+
}
|
| 155 |
}
|
| 156 |
}
|
| 157 |
+
|
| 158 |
+
if (col_energy) free(col_energy);
|
| 159 |
+
if (g) hpc_destroy(g);
|
| 160 |
}
|
| 161 |
|
| 162 |
/* ── Helper: RMS norm (OpenMP) ── */
|
|
|
|
| 252 |
if (!qkv) { free(normed); free(attn_out); return; }
|
| 253 |
|
| 254 |
/* Graph-based matmul: importance via HPCGraph marginals */
|
| 255 |
+
printf("matmul qkv M=%ld K=%ld N=%ld\n", (long)seq_len, (long)n_embd, (long)qkv_dim); fflush(stdout); hpc_matmul_graph(normed, qkv_w, qkv, imp_qkv, cnt_qkv,
|
| 256 |
+
seq_len, n_embd, qkv_dim, 0);
|
| 257 |
|
| 258 |
/* Split Q, K, V */
|
| 259 |
int64_t q_total = n_head * head_dim;
|
|
|
|
| 372 |
|
| 373 |
/* Gate projection if present */
|
| 374 |
if (gate_w && gate_rows > 0) {
|
| 375 |
+
int trans_w = (gate_rows == inner_dim) ? 1 : 0;
|
| 376 |
+
int64_t N_out = trans_w ? n_embd : gate_rows;
|
| 377 |
+
float *gated = (float *)malloc(seq_len * N_out * sizeof(float));
|
| 378 |
if (gated) {
|
| 379 |
+
printf("matmul gate M=%ld K=%ld N=%ld trans=%d\n", (long)seq_len, (long)inner_dim, (long)N_out, trans_w); fflush(stdout); hpc_matmul_graph(attn_inner, gate_w, gated, imp_gate, cnt_gate,
|
| 380 |
+
seq_len, inner_dim, N_out, trans_w);
|
| 381 |
for (int64_t t = 0; t < seq_len; t++) {
|
| 382 |
+
int64_t copy_dim = N_out < n_embd ? N_out : n_embd;
|
| 383 |
+
memcpy(attn_out + t * n_embd, gated + t * N_out, copy_dim * sizeof(float));
|
| 384 |
}
|
| 385 |
free(gated);
|
| 386 |
}
|
|
|
|
| 401 |
float *K_buf = (float *)malloc(seq_len * k_dim * sizeof(float));
|
| 402 |
float *V_buf = (float *)malloc(seq_len * v_dim * sizeof(float));
|
| 403 |
if (!Q || !K_buf || !V_buf) {
|
| 404 |
+
if(Q) free(Q); if(K_buf) free(K_buf); if(V_buf) free(V_buf);
|
| 405 |
free(normed); free(attn_out);
|
| 406 |
return;
|
| 407 |
}
|
| 408 |
|
| 409 |
+
hpc_matmul_graph(normed, q_w, Q, imp_q, cnt_q, seq_len, n_embd, q_dim, 0);
|
| 410 |
+
hpc_matmul_graph(normed, k_w, K_buf, imp_k, cnt_k, seq_len, n_embd, k_dim, 0);
|
| 411 |
+
hpc_matmul_graph(normed, v_w, V_buf, imp_v, cnt_v, seq_len, n_embd, v_dim, 0);
|
| 412 |
|
| 413 |
/* Same HPC attention as above but with separate Q/K/V buffers */
|
| 414 |
int64_t hd_q = q_dim / n_head;
|
|
|
|
| 505 |
float *projected = (float *)calloc(seq_len * n_embd, sizeof(float));
|
| 506 |
if (projected) {
|
| 507 |
hpc_matmul_graph(proj_in, o_w, projected, imp_o, cnt_o,
|
| 508 |
+
seq_len, o_cols, n_embd, 0);
|
| 509 |
memcpy(attn_out, projected, seq_len * n_embd * sizeof(float));
|
| 510 |
free(projected);
|
| 511 |
}
|
|
|
|
| 540 |
|
| 541 |
/* Graph-based matmul for FFN with importance */
|
| 542 |
hpc_matmul_graph(normed_ff, ffn_gate_w, gate_out,
|
| 543 |
+
imp_ffn_gate, cnt_ffn_gate, seq_len, n_embd, ffn_dim, 0);
|
| 544 |
hpc_matmul_graph(normed_ff, ffn_up_w, up_out,
|
| 545 |
+
imp_ffn_up, cnt_ffn_up, seq_len, n_embd, ffn_dim, 0);
|
| 546 |
|
| 547 |
/* SiLU(gate) * up */
|
| 548 |
hpc_silu(gate_out, seq_len * ffn_dim);
|
|
|
|
| 551 |
gate_out[i] *= up_out[i];
|
| 552 |
|
| 553 |
/* Down projection: graph-based importance recording */
|
| 554 |
+
float *ff_out_buf = (float *)malloc(seq_len * n_embd * sizeof(float));
|
| 555 |
+
if (ff_out_buf) {
|
| 556 |
+
hpc_matmul_graph(gate_out, ffn_down_w, ff_out_buf,
|
| 557 |
imp_ffn_down, cnt_ffn_down,
|
| 558 |
+
seq_len, ffn_dim, n_embd, 0);
|
| 559 |
/* Residual add */
|
| 560 |
#pragma omp parallel for schedule(static)
|
| 561 |
for (int64_t i = 0; i < total; i++)
|
| 562 |
+
hidden[i] += ff_out_buf[i];
|
| 563 |
+
free(ff_out_buf);
|
| 564 |
}
|
| 565 |
}
|
| 566 |
|