2358 {
2360 auto it =
env.find(
n.in.at(
k));
2361 if (
it ==
env.end())
throw std::runtime_error(
"IR op '" +
n.op +
"': input '" +
n.in.at(
k) +
"' is not defined");
2363 throw std::runtime_error(
"IR op '" +
n.op +
"': input '" +
n.in.at(
k) +
"' is " +
2364 (
want_list ?
"a tensor, not a list" :
"a list, not a tensor"));
2366 };
2367 auto in = [&](
const Node&
n,
size_t k) -> Buf& {
return value(
n,
k,
false); };
2368 auto list_in = [&](
const Node&
n,
size_t k) -> Buf& {
return value(
n,
k,
true); };
2369 auto wname = [&](
const Node&
n) {
2373 };
2374 for (
const auto&
n :
nodes) {
2377 if (
n.op ==
"embedding") {
2378 const auto& tokens =
in(
n, 0);
2381 const int d =
static_cast<int>(
shapes_.at(
wn).at(0));
2382 Buf
out{std::vector<float>(
static_cast<size_t>(
T) * d), d};
2383
2384
2385 const bool ext =
has(
n.attrs,
"state_weight");
2386 for (
int t = 0;
t <
T; ++
t) {
2387 const int id =
static_cast<int>(tokens.v[
t]);
2388 const Weight*
src = &
W;
2392 throw std::runtime_error("IR embedding: token id " + std::to_string(id) + " is past the state slots (vocab " +
2393 std::to_string(
vocab_) +
", k " + std::to_string(
state_k_) +
")");
2397 throw std::runtime_error("IR embedding: token id " + std::to_string(id) + " out of range");
2398 }
2399 float*
dst =
out.v.data() +
static_cast<size_t>(
t) * d;
2400 if (
src->quantised())
2402 else
2403 std::memcpy(
dst,
src->f32.data() +
static_cast<size_t>(
row) * d, d *
sizeof(
float));
2404 }
2405 env[
n.out.at(0)] = std::move(
out);
2406 }
else if (
n.op ==
"pos_embedding") {
2410 const int d =
x.width;
2411 if (
shapes_.at(
wn).at(0) != d)
throw std::runtime_error(
"IR pos_embedding '" +
wn +
"': width differs from x");
2412 if (
static_cast<size_t>(
start_pos +
T) * d >
P.size())
2413 throw std::runtime_error(
"IR pos_embedding: position " + std::to_string(
start_pos +
T - 1) +
" exceeds '" +
wn +
"'");
2414 for (
int t = 0;
t <
T; ++
t)
2415 for (
int i = 0;
i < d; ++
i)
x.v[
static_cast<size_t>(
t) * d +
i] +=
P[
static_cast<size_t>(
start_pos +
t) * d +
i];
2416 env[
n.out.at(0)] = std::move(
x);
2417 }
else if (
n.op ==
"layernorm") {
2418 const Buf&
x =
in(
n, 0);
2421 const float eps =
n.attrs.value(
"eps", 1e-5f);
2422 const int d =
x.width;
2423 Buf
out{std::vector<float>(
x.v.size()), d};
2424 for (
int t = 0;
t <
T; ++
t) {
2425 const float*
r =
x.v.data() +
static_cast<size_t>(
t) * d;
2427 for (
int i = 0;
i < d; ++
i)
mean +=
r[
i];
2431 const float inv =
static_cast<float>(1.0 / std::sqrt(
var +
eps));
2432 for (
int i = 0;
i < d; ++
i)
2433 out.v[
static_cast<size_t>(
t) * d +
i] = (
r[
i] -
static_cast<float>(
mean)) *
inv *
w[
i] +
b[
i];
2434 }
2435 env[
n.out.at(0)] = std::move(
out);
2436 }
else if (
n.op ==
"split") {
2437 const Buf&
x =
in(
n, 0);
2438 const auto sizes =
n.attrs.at(
"sizes").get<std::vector<int>>();
2441 if (
sizes.size() !=
n.out.size())
throw std::runtime_error(
"IR split: sizes do not match the outputs");
2442
2443 const int groups =
n.attrs.contains(
"groups") ?
n.attrs.at(
"groups").get<
int>() : 1;
2444 if (
groups < 1)
throw std::runtime_error(
"IR_SPEC 5.5 (rule 10): split groups " + std::to_string(
groups) +
" is not positive");
2446 throw std::runtime_error(
"IR_SPEC 5.5 (rule 37): split sizes sum to " + std::to_string(
total) +
2448 ", not the input width " + std::
to_string(
x.width));
2450 std::vector<Buf>
parts;
2451 std::vector<float*>
ptrs;
2456 continue;
2457 }
2459 for (
size_t o = 0;
o <
sizes.size(); ++
o) {
2461 for (
int t = 0;
t <
T; ++
t)
2462 std::memcpy(
part.v.data() +
static_cast<size_t>(
t) *
sizes[
o],
x.v.data() +
static_cast<size_t>(
t) *
x.width +
col,
2463 sizes[
o] *
sizeof(
float));
2466 }
2467 }
else if (
n.op ==
"gelu") {
2468 const Buf&
x =
in(
n, 0);
2469 const bool tanh_form =
n.attrs.value(
"approx",
"none") ==
"tanh";
2470 Buf
out{std::vector<float>(
x.v.size()),
x.width};
2471 const float c = std::sqrt(2.0f / 3.14159265358979323846f);
2472 for (
size_t i = 0;
i <
x.v.size(); ++
i) {
2473 const float v =
x.v[
i];
2475 : 0.5f *
v * (1.0f + std::
erf(
v / std::
sqrt(2.0f)));
2476 }
2477 env[
n.out.at(0)] = std::move(
out);
2478 }
else if (
n.op ==
"rmsnorm") {
2479 const Buf&
x =
in(
n, 0);
2480 Buf
out{{},
x.width};
2481 out.v.resize(
x.v.size());
2482
2483
2484 const int g =
has(
n.attrs,
"group") ?
n.attrs.at(
"group").get<
int>() :
x.width;
2486 if (g > 0 &&
x.width % g != 0)
2487 throw std::runtime_error(
"IR_SPEC 5.6 (rule 37): rmsnorm '" +
wname(
n) +
"': group " + std::to_string(g) +
2488 " does not divide the input width " + std::to_string(
x.width));
2489 if (g <= 0 ||
x.width % g != 0 ||
w.size() !=
static_cast<size_t>(g))
2490 throw std::runtime_error(
"IR rmsnorm '" +
wname(
n) +
"': group " + std::to_string(g) +
" does not fit width " +
2491 std::to_string(
x.width) +
" and weight [" + std::to_string(
w.size()) +
"]");
2493 env[
n.out.at(0)] = std::move(
out);
2494 }
else if (
n.op ==
"linear") {
2495 const Buf&
x =
in(
n, 0);
2499 throw std::runtime_error(
"IR linear '" +
wn +
"': input width " + std::to_string(
x.width) +
2500 " does not match the weight's ne0 " + std::to_string(
shapes_.at(
wn).at(0)));
2507 },
2509 else
2511 if (
has(
n.attrs,
"bias")) {
2513 for (
int t = 0;
t <
T; ++
t)
2515 }
2516 env[
n.out.at(0)] = std::move(
out);
2517 }
else if (
n.op ==
"rope") {
2518 Buf q =
in(
n, 0),
k =
in(
n, 1);
2519 const int hd =
n.attrs.at(
"head_dim").get<
int>();
2524 true);
2525 } else {
2527 throw std::runtime_error(
"IR rope: position " + std::to_string(
start_pos +
T - 1) +
" exceeds the rope table (" +
2529 if (q.width %
hd != 0 ||
k.width %
hd != 0)
throw std::runtime_error(
"IR rope: q/k widths are not whole heads");
2532 }
2533 env[
n.out.at(0)] = std::move(q);
2534 env[
n.out.at(1)] = std::move(
k);
2535 }
else if (
n.op ==
"attention") {
2536 const Buf &q =
in(
n, 0), &
k =
in(
n, 1), &
v =
in(
n, 2);
2537 const int hd =
n.attrs.at(
"head_dim").get<
int>(),
hq =
n.attrs.at(
"heads").get<
int>();
2538 const int hkv =
n.attrs.at(
"kv_heads").get<
int>();
2539 if (
hd !=
head_dim_ ||
hkv !=
kv_heads_)
throw std::runtime_error(
"IR attention shape differs from its kv state");
2540
2541
2542
2543
2544 const bool ts =
n.attrs.value(
"mask",
"causal") ==
"turn_state";
2547 throw std::runtime_error(
"IR attention: position " + std::to_string(
kpos +
T) +
" exceeds the kv state (" +
2550 const size_t row =
static_cast<size_t>(
hkv) *
hd;
2551 std::memcpy(
cache.k.data() +
kpos *
row,
k.v.data(),
static_cast<size_t>(
T) *
row *
sizeof(
float));
2552 std::memcpy(
cache.v.data() +
kpos *
row,
v.v.data(),
static_cast<size_t>(
T) *
row *
sizeof(
float));
2556 }
2557 const float scale =
n.attrs.contains(
"scale") ?
n.attrs.at(
"scale").get<
float>() : 1.0f / std::
sqrt(
float(
hd));
2561
2562 const float softcap =
has(
n.attrs,
"softcap") ?
at_layer(
n.attrs.at(
"softcap"), std::max(
layer, 0)).get<
float>() : 0.0f;
2563 if (
has(
n.attrs,
"position_bias")) {
2564 const json&
pb =
n.attrs.at(
"position_bias");
2565 const std::vector<int>
buckets =
pb.at(
"buckets").get<std::vector<int>>();
2567 std::vector<int>
qpos(
static_cast<size_t>(
T));
2569
2571 attention_bias_batch_cpu(q.v,
cache,
out.v,
T,
rows,
ts ? &
kv_pos_ :
nullptr,
qpos,
hq,
hkv,
hd,
scale,
W.data(),
2573 }
else if (
has(
n.attrs,
"relative_kv")) {
2574 const json&
rk =
n.attrs.at(
"relative_kv");
2575 const int K =
rk.at(
"max_distance").get<
int>();
2576
2577 auto table = [&](
const char*
member,
int&
w) ->
const float* {
2582 if (
s.size() != 2 ||
s[1] != K + 1 || (
s[0] !=
hd &&
s[0] !=
static_cast<int64_t>(
hq) *
hd))
2583 throw std::runtime_error(
"IR_SPEC 5.15 (rule 40): relative_kv " + std::string(
member) +
" '" +
name +
2584 "' is not of ne {head_dim or heads * head_dim, max_distance + 1}");
2585 w =
static_cast<int>(
s[0]);
2587 };
2591 std::vector<int>
qpos(
static_cast<size_t>(
T));
2594 attention_relkv_batch_cpu(q.v,
cache,
out.v,
T,
rows,
ts ? &
kv_pos_ :
nullptr,
qpos,
hq,
hkv,
hd,
scale,
RK,
rk_w,
2599
2600
2601
2602
2603
2606 throw std::runtime_error(
"IR depth_route: application " + std::to_string(
layer) +
" runs " +
2607 std::to_string(
T) +
" rows over " + std::to_string(
held.size()) +
2608 " held positions for " + std::to_string(
attn_row_) +
" rows");
2611 std::vector<std::vector<int>>
rows(1);
2617 attention_window_batch_cpu(q.v,
cache,
out.v,
T,
start_pos,
hq,
hkv,
hd,
scale,
window,
sinks,
softcap);
2618 else
2620 env[
n.out.at(0)] = std::move(
out);
2621 }
else if (
n.op ==
"mla_attention") {
2623 const int L = std::max(
layer, 0);
2624 auto at = [&](
const char*
k) {
return at_layer(
n.attrs.at(
k),
L).get<
int>(); };
2625 const int H =
at(
"heads"),
r =
at(
"kv_rank"),
dn =
at(
"qk_nope"),
dr =
at(
"qk_rope"),
dv =
at(
"v_head_dim");
2626 if (
qn.width !=
H *
dn ||
qr.width !=
H *
dr ||
c.width !=
r ||
kr.width !=
dr)
2627 throw std::runtime_error(
"IR_SPEC 5.20 (rule 37): mla_attention reads qn " + std::to_string(
qn.width) +
", qr " +
2628 std::to_string(
qr.width) +
", c " + std::to_string(
c.width) +
" and kr " +
2629 std::to_string(
kr.width) +
" wide, not heads x qk_nope " + std::to_string(
H *
dn) +
2630 ", heads x qk_rope " + std::to_string(
H *
dr) +
", kv_rank " + std::to_string(
r) +
2631 " and qk_rope " + std::to_string(
dr));
2633 throw std::runtime_error(
"IR mla_attention: position " + std::to_string(
start_pos +
T) +
" exceeds the kv state (" +
2635
2637 const size_t w =
static_cast<size_t>(
r) +
dr;
2638 for (
int t = 0;
t <
T; ++
t) {
2640 std::memcpy(
dst,
c.v.data() +
static_cast<size_t>(
t) *
r,
static_cast<size_t>(
r) *
sizeof(
float));
2641 std::memcpy(
dst +
r,
kr.v.data() +
static_cast<size_t>(
t) *
dr,
static_cast<size_t>(
dr) *
sizeof(
float));
2642 }
2647 Buf
out{std::vector<float>(
static_cast<size_t>(
T) *
H *
dv),
H *
dv};
2649 attention_visible_rows(
T,
start_pos,
window,
sinks),
H,
r,
dn,
dr,
dv,
Kb.data(),
Vb.data(),
2650 n.attrs.at(
"scale").get<
float>());
2651 env[
n.out.at(0)] = std::move(
out);
2652 }
else if (
n.op ==
"add" ||
n.op ==
"mul") {
2653 const Buf &
a =
in(
n, 0), &
b =
in(
n, 1);
2655 Buf
out{std::vector<float>(
a.v.size()),
a.width};
2657 for (
size_t i = 0;
i <
a.v.size(); ++
i)
out.v[
i] =
a.v[
i] +
b.v[
i];
2658 else
2659 for (
size_t i = 0;
i <
a.v.size(); ++
i)
out.v[
i] =
a.v[
i] *
b.v[
i];
2660 env[
n.out.at(0)] = std::move(
out);
2661 }
else if (
n.op ==
"moe_ffn") {
2662 const Buf&
x =
in(
n, 0);
2663 const auto&
ex =
n.attrs.at(
"experts");
2669 const int E =
n.attrs.at(
"n_experts").get<
int>(),
k =
n.attrs.at(
"top_k").get<
int>();
2671 if (
gs.size() != 3 ||
gs[0] !=
x.width ||
gs[2] != E)
2672 throw std::runtime_error(
"IR moe_ffn '" +
gn +
"': expert stack shape does not match d and n_experts");
2673 const int d =
x.width,
d_ff =
static_cast<int>(
gs[1]);
2674 const bool renorm =
n.attrs.value(
"gate_norm",
"renorm") ==
"renorm";
2675
2679 : nullptr;
2681 if (
has(
n.attrs,
"groups")) {
2682 groups_n =
n.attrs.at(
"groups").at(
"n").get<
int>();
2683 groups_top =
n.attrs.at(
"groups").at(
"top").get<
int>();
2685 throw std::runtime_error(
"IR_SPEC 5.16 (rule 10): moe_ffn groups {n " + std::to_string(
groups_n) +
", top " +
2686 std::to_string(
groups_top) +
"} do not fit n_experts " + std::to_string(E) +
" and top_k " +
2688 }
2689 Buf
out{std::vector<float>(
static_cast<size_t>(
T) * d), d};
2690#pragma omp parallel for schedule(static)
2691 for (
int t = 0;
t <
T; ++
t)
2694 env[
n.out.at(0)] = std::move(
out);
2695 }
else if (
n.op ==
"silu") {
2696 const Buf&
x =
in(
n, 0);
2697 Buf
out{std::vector<float>(
x.v.size()),
x.width};
2699 env[
n.out.at(0)] = std::move(
out);
2700 }
else if (
n.op ==
"sub") {
2701 const Buf &
a =
in(
n, 0), &
b =
in(
n, 1);
2703 Buf
out{std::vector<float>(
a.v.size()),
a.width};
2705 env[
n.out.at(0)] = std::move(
out);
2706 }
else if (
n.op ==
"relu" ||
n.op ==
"sigmoid") {
2707 const Buf&
x =
in(
n, 0);
2708 Buf
out{std::vector<float>(
x.v.size()),
x.width};
2710 env[
n.out.at(0)] = std::move(
out);
2711 }
else if (
n.op ==
"affine") {
2712 const Buf&
x =
in(
n, 0);
2713 Buf
out{std::vector<float>(
x.v.size()),
x.width};
2716 env[
n.out.at(0)] = std::move(
out);
2717 }
else if (
n.op ==
"scale") {
2718 const Buf&
x =
in(
n, 0);
2721 const int d =
x.width;
2722 if (d <= 0 || g.size() != static_cast<size_t>(d))
2723 throw std::runtime_error(
"IR_SPEC 5.4 (rule 37): scale '" +
wn +
"' has " + std::to_string(g.size()) +
2724 " values for width " + std::to_string(d));
2725 const float*
b =
nullptr;
2726 if (
has(
n.attrs,
"bias")) {
2729 if (
B.size() !=
static_cast<size_t>(d))
2730 throw std::runtime_error(
"IR_SPEC 5.4 (rule 37): scale bias '" +
bn +
"' has " + std::to_string(
B.size()) +
2731 " values for width " + std::to_string(d));
2733 }
2734 Buf
out{std::vector<float>(
x.v.size()), d};
2735 cpu::scale(
x.v.data(), g.data(),
b,
out.v.data(),
static_cast<int>(
x.v.size() / d), d);
2736 env[
n.out.at(0)] = std::move(
out);
2737 }
else if (
n.op ==
"mul_col") {
2738 const Buf &
x =
in(
n, 0), &
c =
in(
n, 1);
2739 if (
c.width != 1 ||
c.v.size() !=
static_cast<size_t>(
T) ||
x.v.size() !=
static_cast<size_t>(
T) *
x.width)
2740 throw std::runtime_error("IR_SPEC 5.12 (rule 37): mul_col: c must be [T, 1] beside x [T, w]");
2741 Buf
out{std::vector<float>(
x.v.size()),
x.width};
2743 env[
n.out.at(0)] = std::move(
out);
2744 }
else if (
n.op ==
"rms_row") {
2745 const Buf&
x =
in(
n, 0);
2746 if (
x.width <= 0 ||
x.v.size() !=
static_cast<size_t>(
T) *
x.width)
2747 throw std::runtime_error("IR rms_row: input is not [T, w]");
2748 Buf
out{std::vector<float>(
static_cast<size_t>(
T)), 1};
2750 env[
n.out.at(0)] = std::move(
out);
2751 }
else if (
n.op ==
"expr") {
2752 std::vector<const float*>
ptrs;
2753 const Buf&
x0 =
in(
n, 0);
2754 for (
size_t k = 0;
k <
n.in.size(); ++
k) {
2755 const Buf&
a =
in(
n,
k);
2756 if (
a.width !=
x0.width ||
a.v.size() !=
x0.v.size())
2757 throw std::runtime_error("IR_SPEC 5.19 (rule 37): expr inputs must share one shape [T, w]");
2758 ptrs.push_back(
a.v.data());
2759 }
2760 if (
x0.width <= 0 ||
x0.v.size() %
x0.width)
throw std::runtime_error(
"IR expr: input is not [T, w]");
2761 Buf
out{std::vector<float>(
x0.v.size()),
x0.width};
2763 static_cast<int>(
x0.v.size() /
x0.width),
x0.width,
out.v.data());
2764 env[
n.out.at(0)] = std::move(
out);
2765 }
else if (
n.op ==
"list") {
2768 for (
size_t k = 0;
k <
n.in.size(); ++
k)
out.items.push_back(
in(
n,
k));
2769 env[
n.out.at(0)] = std::move(
out);
2770 }
else if (
n.op ==
"append") {
2771 const Buf&
x =
in(
n, 1);
2772
2774 if (
n.out.at(0) ==
n.in.at(0))
2776 else
2778 out.items.push_back(
x);
2779 env[
n.out.at(0)] = std::move(
out);
2780 }
else if (
n.op ==
"depth_attend") {
2782 std::vector<const float*>
src;
2783 int d = 0;
2785 if (d == 0) d =
s.width;
2786 if (
s.width != d || d <= 0 ||
s.v.size() !=
static_cast<size_t>(
T) * d)
2787 throw std::runtime_error("IR_SPEC 5.18 (rule 37): depth_attend sources must all be one shape [T, d]");
2788 src.push_back(
s.v.data());
2789 };
2792 if (
src.empty())
throw std::runtime_error(
"IR depth_attend: no sources");
2793 const float*
w =
nullptr;
2794 if (
src.size() > 1) {
2796 if (!
weights_.count(
wn))
throw std::runtime_error(
"IR depth_attend: pseudo-query '" +
wn +
"' is not in the GGUF");
2798 if (
W.size() !=
static_cast<size_t>(d))
2799 throw std::runtime_error(
"IR depth_attend: pseudo-query '" +
wn +
"' is not [d]");
2801 }
2802 Buf
out{std::vector<float>(
static_cast<size_t>(
T) * d), d};
2804 env[
n.out.at(0)] = std::move(
out);
2805 }
else if (
n.op ==
"linear_attention") {
2806 const Buf &q =
in(
n, 0), &
k =
in(
n, 1), &
v =
in(
n, 2);
2807 const int w =
n.attrs.at(
"heads").get<
int>() *
n.attrs.at(
"head_dim").get<
int>();
2808 if (q.width !=
w ||
k.width !=
w ||
v.width !=
w)
2809 throw std::runtime_error("IR linear_attention: q/k/v widths do not match heads * head_dim");
2810 const RecSlot& slot =
rec_slot(
n,
"linear_attention");
2813 const float floor =
n.attrs.value(
"den_floor", 1e-8f);
2814 Buf
out{std::vector<float>(
static_cast<size_t>(
T) *
w),
w};
2815 for (
int t = 0;
t <
T; ++
t) {
2816 const size_t r =
static_cast<size_t>(
t) *
w;
2819 }
2820 env[
n.out.at(0)] = std::move(
out);
2821 }
else if (
n.op ==
"ssm_scan") {
2822 const Buf&
u =
in(
n, 0);
2823 const int sn =
n.attrs.at(
"n").get<
int>();
2824 if (
u.width !=
sn)
throw std::runtime_error(
"IR ssm_scan: input width differs from n");
2825 const RecSlot& slot =
rec_slot(
n,
"ssm_scan");
2832 Buf
out{std::vector<float>(
static_cast<size_t>(
T) *
sn),
sn};
2833 for (
int t = 0;
t <
T; ++
t) {
2834 const size_t r =
static_cast<size_t>(
t) *
sn;
2837 }
2838 env[
n.out.at(0)] = std::move(
out);
2839 }
else if (
n.op ==
"conv1d_causal") {
2840 const Buf&
x =
in(
n, 0);
2841 const int C =
n.attrs.at(
"channels").get<
int>(), K =
n.attrs.at(
"kernel").get<
int>();
2842 if (
x.width !=
C)
throw std::runtime_error(
"IR conv1d_causal: input width differs from channels");
2843 const RecSlot& slot =
rec_slot(
n,
"conv1d_causal");
2848 Buf
out{std::vector<float>(
static_cast<size_t>(
T) *
C),
C};
2849 for (
int t = 0;
t <
T; ++
t) {
2850 const size_t r =
static_cast<size_t>(
t) *
C;
2853 }
2854 env[
n.out.at(0)] = std::move(
out);
2855 }
else if (
n.op ==
"selective_scan") {
2857 const int D =
n.attrs.at(
"channels").get<
int>(),
N =
n.attrs.at(
"d_state").get<
int>();
2858 if (
x.width !=
D ||
dt.width !=
D ||
bm.width !=
N ||
cm.width !=
N)
2859 throw std::runtime_error("IR selective_scan: x/dt must be [T, channels] and B/C [T, d_state]");
2860 const RecSlot& slot =
rec_slot(
n,
"selective_scan");
2864 const bool softplus =
n.attrs.value(
"dt_softplus",
true);
2865 Buf
out{std::vector<float>(
static_cast<size_t>(
T) *
D),
D};
2866 for (
int t = 0;
t <
T; ++
t) {
2868 bm.v.data() +
static_cast<size_t>(
t) *
N,
cm.v.data() +
static_cast<size_t>(
t) *
N,
2871 }
2872 env[
n.out.at(0)] = std::move(
out);
2873 }
else if (
n.op ==
"recurrence") {
2875 const RecSlot& slot =
rec_slot(
n,
"recurrence");
2876 std::vector<const Buf*>
ins;
2877 for (
size_t k = 0;
k <
n.in.size(); ++
k) {
2878 const Buf&
b =
in(
n,
k);
2879 if (
b.is_list ||
static_cast<size_t>(
b.width) !=
prog.input_widths()[
k] ||
2880 b.v.size() !=
static_cast<size_t>(
T) *
b.width)
2881 throw std::runtime_error(
"IR_SPEC 6.10 (rule 34): recurrence input '" +
n.in[
k] +
"' is " +
2882 std::to_string(
b.width) +
" wide; its declaration is " +
2883 std::to_string(
prog.input_widths()[
k]));
2885 }
2886 std::vector<const float*>
w;
2888 std::vector<float*>
st;
2891 const size_t ow =
prog.out_width();
2892 Buf
out{std::vector<float>(
static_cast<size_t>(
T) *
ow),
static_cast<int>(
ow)};
2893 std::vector<const float*>
row(
ins.size());
2894 for (
int t = 0;
t <
T; ++
t) {
2895 for (
size_t k = 0;
k <
ins.size(); ++
k)
row[
k] =
ins[
k]->
v.data() +
static_cast<size_t>(
t) *
ins[
k]->width;
2898 }
2899 env[
n.out.at(0)] = std::move(
out);
2900 }
2901 }
2902}
void rec_row_done(const RecSlot &slot, int layer, int t)
const std::vector< std::pair< float, float > > & rope_table(int layer) const
std::vector< std::vector< int > > ts_vis_
float * rec_tensor(const RecSlot &slot, const char *tensor, int layer, size_t floats)
void attention_window_batch_cpu(const std::vector< float > &q_batch_roped, KVCacheLayer ¤t_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, int start_pos_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, int window, int sinks, float softcap)
std::vector< std::vector< int > > attention_visible_rows(int num_tokens_in_batch, int start_pos_in_sequence, int window, int sinks)
void attention_batch_cpu(const std::vector< float > &q_batch_roped, KVCacheLayer ¤t_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, int start_pos_in_sequence, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, float softcap)
void attention_bias_batch_cpu(const std::vector< float > &q_batch_roped, const KVCacheLayer ¤t_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< std::vector< int > > &rows, const std::vector< int > *key_pos, const std::vector< int > &query_pos, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, const float *bias, const std::vector< int > &buckets, float softcap)
void attention_rows_batch_cpu(const std::vector< float > &q_batch_roped, const KVCacheLayer ¤t_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< std::vector< int > > &rows, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, float softcap)
void swa_visible_ranges(int pos, int window, int sinks, int &sink_hi, int &win_lo)
void attention_relkv_batch_cpu(const std::vector< float > &q_batch_roped, const KVCacheLayer ¤t_layer_kv_cache, std::vector< float > &batch_attn_output, int num_tokens_in_batch, const std::vector< std::vector< int > > &rows, const std::vector< int > *key_pos, const std::vector< int > &query_pos, int num_q_heads, int num_kv_heads, int head_dim, float attention_scale, const float *rk, int rk_width, const float *rv, int rv_width, int max_distance, float softcap)
const float * col[expr::kMaxColumns]
void relu(const float *x, float *out, size_t n)
void conv1d_causal_row(const float *x, const float *w, const float *bias, float *state, float *out, int C, int K)
void depth_attend(const std::vector< const float * > &sources, const float *w, float *out, int T, int d, float eps)
void rms_row(const float *x, float *out, int T, int w, float eps)
void sub(const float *a, const float *b, float *out, size_t n)
void sigmoid(const float *x, float *out, size_t n)
void selective_scan_row(const float *x, const float *dt, const float *B, const float *C, const float *A, const float *d, float *s, float *y, int D, int N, bool softplus)
void split_groups(const float *x, int T, const std::vector< int > &sizes, int g, const std::vector< float * > &outs)
void affine(const float *x, float *out, size_t n, float scale, float shift)
void mla_attention(const float *qn, const float *qr, const float *kv, float *out, int T, const std::vector< std::vector< int > > &rows, int H, int r, int dn, int dr, int dv, const float *Kb, const float *Vb, float scale)
void mul_col(const float *x, const float *c, float *out, int T, int w)
void scale(const float *x, const float *g, const float *b, float *out, int T, int w)
void eval(const Expr &e, const std::vector< const float * > &ins, int T, int w, float *out)
void linear_attention_row_cpu(const float *q, const float *k, const float *v, float *num, float *den, float *out, int width, float den_floor)
void ssm_scan_row_cpu(const float *u, const float *A, const float *B, const float *C, float D, float *s, float *scratch, float *y, int n)
void roundtrip_rows(int f, float *x, size_t rows, size_t row)
Key-Value cache for a single transformer layer.
void moe_ffn_routed_f32_cpu(const float *x, int d, int d_ff, int E, int k, const float *router, const float *gate_exps, const float *up_exps, const float *down_exps, float *out, bool renorm, bool sigmoid, const float *bias, int groups_n, int groups_top)
void matmul_rows_f32_batch_cpu(const std::function< void(int64_t, float *)> &row_fn, const float *batch_input_activations, float *batch_output_activations, int num_tokens, int output_dim, int input_dim)
void apply_rope_batch_cpu(std::vector< float > &q_batch, std::vector< float > &k_batch, int num_tokens, int num_q_heads, int num_kv_heads, int head_dim, int start_pos_in_sequence, const std::vector< std::pair< float, float > > &all_freqs_cis, int max_pos_embeddings, bool use_adjacent_pairing)
void silu_cpu(const std::vector< float > &x, std::vector< float > &out)
void rmsnorm_batch_cpu(const std::vector< float > &x_batch, const std::vector< float > &weight, std::vector< float > &out_batch, int num_tokens, int hidden_size, float eps)