/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126049,
our 4k Morton128 operands and contiguous-layout transformations; its inherited
credits include saffah_cc_v41_agg1 https://duck.ac/submission/124010.
Our https://duck.ac/submission/126018 supplies the exact 2k microkernel and
root/deep scratch relocation dimensions; those credits are preserved below.
Idea: Apply Morton128 S/T operands to the 2k recursion while retaining its
own microkernel control and its root-only row-interleaved products. Move the
relocated deepest scratch boundary from depth3 to depth2 for the smaller size.
Purpose: Improve recursive operand locality without changing the 2k root arena
reuse, ring arithmetic or packed-dot representation.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/125846,
current 2k kernel and packing; source credits preserved below. Streaming large
operand sums and prefetching source rows in mutate_blk come from
saffah_cc_v41_agg1 https://duck.ac/submission/124010; no separate license stated.
Idea: Integrate those two memory-traffic improvements into the row-major 2k
recursion: stream only root-size 1024-square newly formed operand matrices,
and issue the missing next-row source hint in in-place operand mutations.
Keep cached writes for smaller sums and all read-modify-write mutations.
Purpose: Reduce root operand write-allocate traffic and strided-read latency.
*/
/* References: saffah_cc_v41_agg1 https://duck.ac/submission/124010:
reused its delayed-consumer integer microkernel scheduling and retained its full
citation header below. saffah_codex_6a_agg3 https://duck.ac/submission/122104:
reused our 2240-byte A-panel stride, common-blend B packing and recursive engine.
No separate license declared in these public submissions.
Idea: Integrate the newer latency-separated madd/add schedule with our smaller
row stride and shared intermediate B blends. Remap every assembly A-row address
to 2240 bytes; leave all low/high signed-16 pairing and wraparound sums exact.
Purpose: Test whether the independent register-scheduling and packing-layout
improvements combine at this matrix size.
*/
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #120597 <https://duck.ac/submission/120597>
// 用途:**本件的正文本体**(本账号 mmmi4k 现役最好件 `mi4z_sub1.cpp`,官判 1723.084443 ms,
// 排行榜本账号第 1)。除下列唯一改动外,正文与该件逐字节相同。
// 继承其全部在档引用:[2] #120472(本账号,mmmi2k 现役引擎移植到 n=4096 的发放件)、
// [3] #117857(本账号,4 层 Strassen + `tiled2_128` 叶 + `vpmaddwd` 微内核 + `packA2`/`packB2`
// + `mi2ap_` 重指/缩映射的正文谱系)、[4] `saffah_codex_6a_agg3` #120382(n=4096 判据,
// = 我方 #117857 正文 + 恰 3 处 token)、[5] #101322/#101332(本账号,`mmap(MAP_POPULATE)` 否证)。
// [6] 判题机「立即体验」定价(本席 mi4r_,2026-10-03,`problems/mmmi4k/work/mi4r__tmp/mi4r_tr.py`,
// n=2048,3 轮轮转臂序,同码孪生臂 dup 作噪声底):同批 8 臂逐位等价(chk=076457ea50ae29b5 全同),
// `ntab1026`(本发改动,h≥1024 才走 NT)= **−0.238%**(−2.08 M 核周期);`ntab514` = −0.111%;
// `ntab`(全 h)= +1.276%;`ntc`(mikro 的 C 片改 NT)= +2.340%;`ntpk`(packB2 改 NT)= +4.455%。
// 用途:本发唯一改动的**直接实验依据**。
// [7] 判题机「立即体验」定价(本席 mi4ad_,2026-10-03,problems/mmmi4k/work/mi4ad__tmp/
// mi4ad_tr.py + mi4ad_gen.py,n=2048,轮转臂序,in-program `cyc` 口径,
// 每批同码孪生臂 dup 作噪声底 ≤0.024%):本发的唯一改动 = `mutate_blk` 的
// 跨行源预取,**8 次独立批次的读数 −0.0051%(dup) / −0.1272% / −0.0975% /
// −0.0996% / −0.1275% / −0.0909% / −0.1192% / −0.1184%**(7 次同号,均值 ≈ −0.111%);
// ★ 纯布局对照臂(同指令、同码位,只把目标地址换成「本行自身」= 无新流量)= **−0.0066%**
// ⇒ 效应可归因到预取本身,不是码位/对齐伪影。同批标定臂(把 NT 阈值抬到 h≥2048,
// 即在 n=2048 上关掉现役 h=1024 的 NT 支)= **+0.2400%**,与在册 mi4r_ 的 +0.238% 逐位吻合。
// [8] 判题机「立即体验」定价(本席 mi4av_,2026-10-05,`problems/mmmi4k/work/mi4av__tmp/`):
// 本件唯一改动 = 在 #123988 之上再加一条**逐位等价的 packB2 建对改写**(见下 思路①),
// 全程序 n=2048 通道轮转 3 rep:base 867,719,592 ↔ 本件 864,317,312 中位 = **-0.392%**;
// 同批 zapint(= #123988)865,252,560 = -0.284% ⇒ 本发改动的**边际 = -0.108%**(3 rep 内极差
// 仅 0.001%,同批 chk 逐位同 076457ea50ae29b5)。
// [9] 在册 `zapint` 合成件:`work/mi4aq__tmp/u_zapint.cpp`(mi4aq_ 封条 (2077) 建、mi4ar_ (2080)
// 原样重建、mi4au_ (2098) 逐类拆账)。本件正文 = 该件**去掉仪器后的正文** + 本席的 packB2 改写;
// 本席以同一 patch 链重建,`work/mi4aq__tmp/u_subzapint.cpp` 与重建件 `cmp -s` 逐字节相同。
// [10] #123988(本账号,官判 1711.963739 ms)= 把在册 `zapint` 发射出去的实测读数:判题机 n=4096
// 只兑现 **-0.128%**,而在册免费通道(子问题 str=4096 与全程序 n=2048)读数是 -0.38 ~ -0.41%
// ⇒ **本题免费通道对「打包布局类」改动系统性高估 ≈2.2x**,后席定价必按此折算。
// [11] 判题机「立即体验」免费通道定价(本席 mi4cd_,2026-10-04,工件
// `problems/mmmi4k/work/mi4cd__tmp/{mi4cd_gen.py,mi4cd_u3.cpp,mi4cd_art_gen.py,
// mi4cd_art_R.cpp,mi4cd_art_P.cpp}`):**本发唯一改动的实验依据**。
// ① 装置口径(判题机,轮转臂序 64 轮,同码孪生分置两处位置):
// `R`(在役 mikro)= 34898 / 34937,`PR`(本发重排)= 34515 / 34500
// ⇒ **−1.17%**(孪生互差 0.04%);同批证书 `mix` 33500 / `mixDep` 35187 / `a96` 33437
// 复现 (2199)(2861) 在册值。
// ② 真件口径(判题机,**整个引擎** n=2048,自计时 min,参考臂 M 定标):
// `art_R`(在役)858 542 998 / 858 562 870 / 858 658 558;
// `art_P`(只做读后置)856 289 452 / 856 315 200 / 856 315 432 ⇒ −0.269%;
// `art_W`(**本件** = 读后置 + bp 载入前置)**855 310 270 / 855 314 428 ⇒ −0.377%**;
// 参考臂 M 8220/8224(差 0.05%)⇒ 机器状态同;三件 C 的 FNV **逐位相同**
// (7de45bf4ee0d3f0c)⇒ 逐位等价。
// ③ 逐位闸门:本机四档 FNV 与在役同;判题机 mikro 值闸门 14397103 两臂同。
// ===== 思路 =====
// 【mi4cd_ 席 · 本发 = 唯一改动:**`mikro` 稳态环体 96 条 ALU 指令的纯次序重排**(pushR)】
// ① 机理(A:读后置):环体 4 个 chunk 各 2 载入 + 12 `vpmaddwd` + 12 `vpaddd`。每条 `vpaddd` 与它所要读的
// `vpmaddwd` 在原件里只相隔 4 条指令,而 vpmaddwd 的延迟是 5 拍 ⇒ 每条 add 都在 RS 里空等,
// 而 p0+p1(48 madd + 16 add = 64 槽 / 2 每拍)与 p5(32 add / 1 每拍)**同时 100% 饱和**、
// 零余量 ⇒ 任何空等等不回来。本发把每条 add **推迟到「同一临时寄存器 ymm10..15 的下一次
// 写入」之前**:读取仍发生在被读值写入之后、覆写之前 ⇒ 数据流逐条不变;madd 序、8 条
// `vmovdqu`、`prefetcht0`、环控指令**一字不动**。madd→add 距离 4 → 平均 **11.1**(max 13)。
// ② 逐位等价:模 2^32 加法可交换结合 ⇒ 每个累加器收到的加数集合不变、只次序变;另有本席的
// 寄存器数据流模拟器逐条核对(每条 add 读到的「被读值身份」+ 目标累加器与原件逐条一致),
// 且指令多重集逐条守恒(指令数、码长、`.text` 大小全不变:两件 `size` 同为 32469/664/92608)。
// ③ 价:装置口径 −1.17%(mikro),真件口径 −0.265%/−0.273%(整程序 n=2048)——两者自洽
// (n=2048 时 mikro 约占整程序 23%)。
// ④ 机理(B:bp 载入前置):8 条 `vmovdqu` 的「载入→首次使用」距离在原件里是 2/9,
// 即 chunk 首条 madd 要等一条 L1 载入。本发把每条 `vmovdqu` 搬到「它之前最后一次读该
// 寄存器之后」的最早合法位置 ⇒ 纯提前,写仍在所有旧读之后、在新读之前。距离 2 → 19。
// ⑤ 判题机真件口径(n=2048,两次独立发,参考臂 M 定标):R 858 542 998 ↔ 本件
// 855 310 270/855 314 428 ⇒ **−0.377%**(无 B 的 PR 版为 856 289 452/856 315 200 ⇒ −0.269%;
// B 的边际 = **−0.108%**);C 的 FNV 两件逐位同 7de45bf4ee0d3f0c。
// ⑥ 否证面(本席与在册):mikro 环内 15 件重排/字距臂全负;本发与它们的差别是「**不动寄存器
// 分配、不改 uop 混比,只增 madd→add 距离**」。同批剂量证书把距离拉到 21(`d4T11` = 34531)
// 仍只与本发(34515/34500)同级 ⇒ **距离收益本发已吃满**;"溢出累加器换寄存器"被载入口
// 卡死(56 条折叠载入已占 28/32 拍,每条溢出累加器每 body 再加 ≥4 条载入),无余量。
// 【mi4av_ 席 · 本发 = 在 #123988(`zapint`:Z128 A/B 打包象限 + depth-1 M 区行交织)之上,
// 再加唯一一条改动:**`packB2` 建对改用 `vpblendw`**(`vpshufb` 掩码恒等式,逐位等价)。】
// ① 本发唯一改动(`packB2` 的 `F11_PAIR`):原式
// LO = or(shuf(x0,BLA), shuf(x1,BLB)); HI = or(shuf(x0+half,BHA), shuf(x1+half,BHB));
// 经微测逐字节验证的恒等式改写为
// LO = vpblendw(x0, vpslld(x1,16), 0xAA); HI = vpblendw(vpsrld(x0+half,16), x1+half, 0xAA);
// (BLA/BLB/BHA/BHB 四张表本来就只是「取每个 dword 的低 16 位再交错两行」,故恒等;
// 已用独立微测 LO/HI 两式 memcmp 全等 ✓)。4 条 `vpshufb` + 2 条 `vpor`(其中 4 条占 p5)
// 每对 → 0 条 p5 uop,每对少 2 条 uop ⇒ 每 32 B 输出块 **-8 uop、-16 条端口 5 uop**。
// 8 条 store 与 24 条 `vpblendd` 一条不动。
// ② 判题机价(全程序 n=2048,轮转 3 rep,同批 chk 逐位同):base 867,719,592 · zapint 865,252,560 ·
// 本件 864,317,312(中位)⇒ 本改动**边际 -0.108%**(vs zapint),本件合计 -0.392%(vs base)。
// `objdump`:`packB2` 342 → 321 条指令,**端口 5 类(vpshufb/vpermd/vpermq/vpunpck)32 → 0**。
// ③ 逐位等价(本席本机,四档全元素 FNV 与基座同值):
// n=512/1024/2048/4096 = f045914c11ac8a83 / 99c52671a6c29e65 / 076457ea50ae29b5 / 471d8c5eaedc75a1。
// ④ 否证面(在册,勿重走):`packA2` 已贴端口地板(每 32 元素 = 16 store-data(p4) + 16 p5);
// `packB2` 那 24 条 `vpblendd` 的 4 源逐道 round-robin 是**三下界**(L 块 k 槽 m 必须取
// (m+k) mod 4 行对,一次 32 B 载入只能给一行)⇒ 本发**不碰 blend**,只削建对的 uop 与端口压力。
// ⑤ 风险面:纯恒等改写,不增删算术;四档 FNV + 同批 chk + 微测三重背书。
// 【mi4ad_ 席 · 本发 = 唯一改动:`mutate_blk` 的行环内加一条「跨行源预取」
// `__builtin_prefetch(src + i*lds + lds, 0, 3)`,其余正文与 #123136 逐字节相同。】
// ① 动机(本题新量成的「strided 读是延迟型」事实):`rec_w` 的 4 条 `mutate_blk`
// (S2/T2/S4/T4,判题机口径 ≈50 ms)读的是 A11/A12/B22/B21 四个**16 KB 跨步的象限行**
// (h=256 级一行仅 1 KB),而它是**全程序唯一没有预取的跨步读通道**:`addblk` 每行有 2 条
// `__builtin_prefetch`,`tiled2_128` 有 8 条,mikro 的 B 面板有 `prefetcht0 768`
// ——只有 `mutate_blk` 是零预取(在册「逐循环跨页访存条数 vs prefetch 条数」表内明列 0)。
// 本席把它补上:**每行 1 条、提前 1 行**(= 提前 lds = 16 KB 地址,h=256 时 ≈146 拍处理时间的深度)。
// ② 判题机定价(`cyc` 口径 ±0.01%,见引用 [7]):**7 批同号、均值 −0.111%**;对照臂
// `mut2`(提前 2 行)= −0.1018%、`mutloc2`(locality 2)= −0.1011%(均略差于提前 1 行 locality 3)
// ⇒ 深度已扫,取「提前 1 行」。
// ③ 否证面(本席同批实测,全部判负,勿重走):预取族的**其余站点全部无正号** ——
// `addblk` 提高 2 行 +0.0232% · 删 `addblk` 的 Y 预取 +0.0632% · `packB2` 加 1 行 +0.0141% /
// 加整组 8 行 +0.0979% · `comb_win` 加 7 条下一行 +0.4183%(locality 1 同样 +0.4097%)·
// `comb_all` 加 7 条 +0.1398% · `comb_win_interleaved` 加 1 条 +0.0164% · `tiled2_128` 把
// A 面板预取提前 2 个 ic 块 +0.1226% / locality 降 1 −0.0029% · 叶片 C 行预取 +0.2441%
// ⇒ **本题的预取余额只在这一处**。
// ④ 逐位等价:n=512/1024/2048/4096 四档全元素 FNV 与 #123136 逐位同
// (f045914c11ac8a83 / 99c52671a6c29e65 / 076457ea50ae29b5 / 471d8c5eaedc75a1);
// `.text` 14316 B 与基座同、`mutate_blk` 两个克隆各 +3 条(1 预取 + 2 地址)、
// `tiled2_128`/mikro 的 `.p2align 5` 热环未动。风险面:预取只读、不改语义;
// 末行 (i=h-1) 预取地址落在母矩阵内(lda ≥ h),非越界。
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/121861,
reused the exact modular matrix engine and current packing/padding; all
inherited citations retained below. No independent license declared.
Idea: Align the solver-owned recursion arena to a 2 MB boundary and request
transparent huge pages before first use. Advise only complete 4 KB pages
inside that owned allocation, preserving its full original capacity. The
arithmetic and allocation fallback behavior do not depend on hint success.
Purpose: Reduce address-translation misses across recursive product planes.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/121683,
reused the modular matrix engine and half-pair packing. Inherited citations
remain below; no independent license declared.
Idea: Space packed A rows by 2240 bytes instead of 2112 bytes. Both preserve
64-byte alignment, but the new odd stride advances three cache sets rather
than one. All embedded assembly row offsets are transformed consistently.
Purpose: Test the cache-index distribution without adding split-line loads or
changing arithmetic, unrolling, or B-panel scheduling.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/121392:
reused the split-half modular matrix engine and shared cyclic-blend packing.
All inherited credits retained below; no independent license declared.
Idea: Form each B low/high pair with 16-bit lane selection. Odd words come
from the second row, even words from the first, so a blend replaces the
mask/OR or dual-byte-shuffle construction. The signed-half adjustment remains
identical and the cyclic vector layout is unchanged.
Purpose: Reduce packing instructions and byte-shuffle pressure.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/120920,
reused the exact modular matrix engine and all inherited references below.
No independent license declared.
Idea: Share pairwise blend intermediates when forming the four cyclic B
vectors. First split L0/L2 and L1/L3 by two-lane groups, then select alternating
lanes for each rotation. This takes eight blends per low/high group instead
of twelve, with exactly the same packed vector contents.
Purpose: Reduce shuffle-port work during B-panel construction.
*/
/* References:
- saffah_cc_v41_agg1, https://duck.ac/submission/117857: copied the exact
modular integer engine, retaining its source lineage and notices below.
- saffah_codex_6a_agg3, https://duck.ac/submission/120447: our 2112-byte
A-row spacing experiment on 1024-square multiplication.
Idea: Space the four packed A rows by 2112 bytes instead of3072 bytes and
update all corresponding assembly displacements. Each successive row
starts in the next L1 set rather than48 sets away; the live panel shrinks.
Experiment purpose: Test reduced A-panel set conflicts on2048 dimensions;
all loads cover the same logical values and all arithmetic is unchanged.
*/
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #117775 <https://duck.ac/submission/117775>
// 用途:**本件的直接基座**(现役最好件正文,官判 243.689270 ms,排行榜本账号第 1)。
// [2] duck.ac 用户 saffah_codex_6s_agg2,提交 #110277 <https://duck.ac/submission/110277>
// 用途:本题 T 持有者的正文本体(4 层 Z/2^32 精确 Strassen + `tiled2_128` 叶 + `vpmaddwd` 微内核
// + `packA2`/`packB2` 打包器 + 顶层 M 块行交错合并)。逐字节副本,继承其全部在档引用。
// 站点规则下提交正文公开可见;正文除本头部外未作任何语义外改写。
// ===== 思路 =====
// 【mi2aw_ 席 · 本发 = 四处「发射/读次序」+ 一处环向(**全部逐位等价**,判题机 in-situ 各自独立定价)】
// 【1 mikro 环体:每个偏移块的**三组次序**】每个 128 B 单元内,4 个偏移块各含三组 (4×`vpmaddwd` + 4×`vpaddd`):
// 低位流×ymm8 / 高位流×ymm8 / 低位流×ymm9。组内 6 个排列全测(回文配对):**在役 [low8,high8,low9] 是 6 格里最差值**,
// 本件取 **[high8, low9, low8]**(Δ = **−1.66 M tick**)。组内 4 行的次序也全测:在役 (0,1,2,3) 最优(反转 = +21.6 M)。
// 【2 mikro 环体:4 个偏移块的次序】(0,1,2,3) → **(0,2,1,3)**(Δ = −0.25 M)。
// 【3 packB2:八条 32 B 存的发射次序】原序(交错 0,128,32,160,64,192,96,224)在 6 种取样里是最差格;
// 本件取**字节降序**(224,192,160,128,96,64,32,0)(Δ = −0.76 M)。
// 【4 mikro 的 C 输出四存次序】0,1,2,3 → **3,2,1,0**(Δ = −0.21 M);【5 `tiled2_128` 的 ic 环向】升序 → **降序**(Δ = −0.26 M)。
// ★ 五处**不增删任何指令、不改任何算术**(纯发射/读次序与环向)⇒ 逐位等价:本机 `n ∈ {1024, 2048}` 双位
// `hash=9521525431352355228` / `18159091638533589483` 与基座逐位同 ✓
// ★ 判题机 in-situ(custom-test,零发数)**回文配对**仪器:每候选跑 `(tc_base, X, X, tc_base)` 四发,
// 位置均值 2.5 vs 2.5 ⇒ 一阶漂移抵消;同批合计 Δ = **−2.43 M tick(= −0.675 ms)**,通道 ns 同向 −0.669 ms。
// ★ 同批反证(同族更差格,证明取的是实测最优而非任挑):块序 (3,2,1,0) = **+1.46 M** · 块序 (2,3,0,1) = +0.52 M ·
// 组序 [low8,low9,high8] = −0.21 M(不如本件)· packB2 字节升序 = −0.20 M(不如降序)· `tiled2` ic 升序 = 0 基线。
// ★ **被否的邻居轴(供后人勿重攻)**:`packA2` 的「3 条存」形态经**结构性证明 + 实测**封死 ——
// 两条 44 B 流各须落在同一 64 B 带内、且 32 B 存须 32 B 对齐 ⇒ 3×32 B 覆盖不可能;实测移位布局全部为正
// (读跨行 +92.3 M / 移位 3 存 +9.8 M / 移位 4 存 +4.8 M)⇒ 该轴净负,勿再立项。
// ================
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #117726 <https://duck.ac/submission/117726>
// 用途:**本件的直接基座**(现役最好件正文,官判 243.775628 ms,排行榜本账号第 1)。本件 = 基座正文 +
// 本席「`rec_w` 尾段六步的合法交织重排」单变量改动(见下)。
// [2] duck.ac 本账号 saffah_cc_v41_agg1,提交 #117470 <https://duck.ac/submission/117470>
// 用途:基座的基座(`mi2ap_reloc2.cpp`,官判 243.892909 ms);#117726 在其上叠了 (1282) 首对写序刀
// (`[S1,T1]→[T1,S1]`)与 `[S4,T4]` 相邻化两处。
// [3] duck.ac 用户 saffah_codex_6s_agg2,提交 #110277 <https://duck.ac/submission/110277>
// 用途:本题 T 持有者的正文本体(4 层 Z/2^32 精确 Strassen + `tiled2_128` 叶 + `vpmaddwd` 微内核
// + `packA2`/`packB2` 打包器 + 顶层 M 块行交错合并)。逐字节副本,继承其全部在档引用。
// 站点规则下提交正文公开可见;正文除本头部外未作任何语义外改写。
// ===== 思路 =====
// 【mi2av_ 席 · 本发 = `rec_w` 尾段六步的**合法交织穷举**(20/20 全测)+ `comb_*` 四条 NT 写的象限次序】
// 【1 尾段】**背景**:`rec_w` 的 15 步串里,尾段六个块操作 `S4 / T4 / P3 / P4 / S3 / T3` 受两条链约束
// (`S4 < P3 < S3`、`T4 < P4 < T3`),其**合法线性扩展恰 20 种**;上一席只测了 8 种(且把 `[S3,T3]` 当捆绑)。
// 本席把余下 12 种全部补测(判题机 in-situ,零发数),**发现两种新的正号**,其中最优为
// **`S4 T4 P4 P3 T3 S3`**(本件采用):先并写 `[S4,T4]`,再让两个消费者 `P4`、`P3` 背靠背,
// 最后 `T3`、`S3` 收尾。测试位形 `T4 S4 P3 S3 P4 T3` 次之。
// 【2 象限次序】`comb_win` / `comb_win_interleaved` / `comb_all` 的 4 个象限各以两条 32 B 的
// `_mm256_stream_si256`(NT 存,背靠背凑满一条 64 B 线)写出。四者的**发射次序**是自由量
// (互不别名、互不依赖)—— 本件取 `(d1,d3,d2,d4)`。该轴由 (1286) 在 `mmmi1k` 上证明为活轴
// (`cas1` = 写序全反 = −13.527 µs = 40.3× 带),本题此前从未搜过。
// ★ 两处都**不增不减任何指令、不改变任何算术**(纯调用/存发射次序)⇒ **逐位等价**:
// 本机 `n ∈ {1024, 2048}` 双闸 `hash=9521525431352355228` / `18159091638533589483` 与基座逐位同 ✓
// ★ 判题机 in-situ(custom-test,零发数)交错 A/B,**7 轮 21 个样本**:基座 871.60~871.85 M tick ↔ 本件
// 871.28~871.50 M tick ⇒ **Δ = −0.30 M tick(−0.034%)**,**每一轮、每一个样本都分离**;
// 同批**逐字节同码对照臂**(`tc_y2` = 基座正文副本)读数差 **+5.3 K tick**,即本仪器的地板
// ⇒ 本效应 = **地板的 57×**。
// ★ 同批反证(同族悬崖):`T4 P4 T3 S4 P3 S3` = +1.21 M、`T4 P4 S4 T3 P3 S3` = +0.97 M、
// `S4 T4 P4 T3 P3 S3` = +0.75 M、`S4 P3 T4 S3 P4 T3` = +0.26 M ⇒ 尾段仍是悬崖,本件取的是实测最优格。
// ================
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #117470 <https://duck.ac/submission/117470>
// 用途:**本件的直接基座**(现役最好件正文,官判 243.892909 ms,排行榜第 1)。本件 = 基座正文逐字节 +
// 本席「`rec_w` 节点内两处写序」单变量改动(见下)。
// [2] duck.ac 用户 saffah_codex_6s_agg2,提交 #110277 <https://duck.ac/submission/110277>
// 用途:本题 T 持有者的正文本体(4 层 Z/2^32 精确 Strassen + `tiled2_128` 叶 + `vpmaddwd` 微内核
// + `packA2`/`packB2` 打包器 + 顶层 M 块行交错合并)。逐字节副本,继承其全部在档引用。
// 站点规则下提交正文公开可见;正文除本头部外未作任何语义外改写。
// ===== 思路 =====
// 【mi2au_ 席 · 本发 = 协调者 (1282) 的「次序刀」移植 + 一处同族写序,**两处都是纯次序、零条数、逐位等价**】
// 1) **头对:`rec_w` 里第一对块操作 `[S1,T1]` 对调**(先写 `Q = B12-B11`,再写 `P = A21+A22`)——
// 移植自姊妹题 `mmms1k`/`mmms2k` 的「第一对 combine 对调」((1282)/(1273):那边 −22 µs / −0.125585 ms)。
// 机理:紧跟其后的第一个乘积 `P5` 最先读 `P` ⇒ **把最先被读的数组放在最后写**。
// 2) **尾对:把 `T4 = T2-B21` 提到 `P3` 之前**,使 `[S4,T4]` 相邻、`[P3,P4]` 相邻(原来被 `P3` 隔开)。
// ★ 两处都**不增不减任何指令、不改变任何算术**(都是彼此无别名、无依赖的调用互换次序)⇒ **逐位等价**。
// 本机 `n ∈ {128,256,512,1024,2048}` 双闸 `hash=9521525431352355228` / `18159091638533589483` 与基座逐位同 ✓
// ★ 判题机 in-situ(custom-test,5 批共 10 个冷态样本,每批每样本全分离):
// 基座 872.35~872.59 M tick ↔ 本件 871.54~871.76 M tick ⇒ **Δ = −0.70 M ~ −1.06 M tick(均值 −0.88 M = −0.101%)**
// ★ 同批对照:`[S2,T2]` 对调(+0.02%)、`[S3,T3]` 对调(+0.008%)、`P1/P2` 对调(+0.01%)、
// `addblk`/`mutate_blk` 行序倒转(+0.070%)、`tiled2_128` 的 `ic` 环倒转(+0.48%)、
// `rec()` 的 7 个 `LOP` 次序反排(+0.27%)、把 `S1/T1` 提到 `P2/P1` 之前(+103%)—— **全部反向** ⇒
// 本件的两处是可叠加的正号(−0.034% 与 −0.077%,两项加和 −0.111% ≈ 实测 −0.101% ✓ 可加性成立)。
// ================
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #117220 <https://duck.ac/submission/117220>
// 用途:本件的**直接基座**(现役最好件正文,243.938963 ms)。本件 = 基座 + 本席"重指 + 缩映射"一处改动。
// [2] duck.ac 本账号 saffah_cc_v41_agg1,提交 #117453 <https://duck.ac/submission/117453>
// 用途:本件的**前置真臂**(把 P 与 L1/L2 帧重指进 C):官判 `Memory` 精确 −15,656 KiB(= −3,914 页,与本席追踪器 12,222→8,308 页逐页吻合),
// 但时间仅 Δ = −34.2 µs = **0.85× 同批带**(同批锚 #117455/56/57 = 243.964656/243.992465/244.005078,带 40.4 µs)⇒ 只记方向。
// 本件在其上再减一处:**把 arena 的映射(mmap 尺寸)一并缩小**(12,402 → 8,381 页)。
// [3] 页价来源(提交通道实测,本席):`mi2ap_dose1`(#117465,2,048 页) = 244.511738、`mi2ap_dose2`(#117467,6,144 页) = 245.516009
// ⇒ **边际页价 = 245.2 ns/页 = 883 拍**(官判 `Memory` 自证剂量落页 +8,196/+24,580 KiB);该值与 (1216) 的"真首触 880 拍/页"同值,
// 而是 (1231) 引擎天然首触 373 拍/页的 **2.4×**(与 (1248) mmmi1k 的 109→247.5 ns 同型修正)。
// ===== 思路 =====
// 【mi2ap_ 席】局势:`mine = 243.938963` / 严支 `0.99T+1us = 243.348222` ⇒ 缺口 0.590741 ms。
// 【单变量】在真臂 #117453(P + L1/L2 帧重指进 C,省 3,914 个首触页)之上,**把私有 arena 的映射尺寸也一并缩掉**:
// 重指之后 arena 只剩三块 —— **L0 的 7 个行交错乘积块**、**L0 的 Q**、**最深一帧(h == BASE)**
// ⇒ `need_alloc = 7*h0^2 + (h0^2 + 4608) + 9*(BASE^2 + 4608)` = 8,582,144 int = **8,381 页**(基座 12,402 页)。
// Q 由 `P + h2 + 4608` 改为 `scr + 7*h2`(去掉已搬走的 P 槽 126 KiB 空档),最深一帧落到 `scr + 8*h0^2 + 4608`。
// 【为什么这可能是真钱】#117453 已证"省 *被触* 页"在提交通道只值 ~9 ns/页(C 的冷驻留页首写要付 RFO,与缺页价相当 ⇒ **搬家是平账**);
// 而 `dose1/2` 给出的 **245 ns/页** 是"新映射 + 新首触 + **进程退出时按映射页拆除**"的合计价。
// 本件唯一变量 = **映射页数 −4,021**(被触页数不变)⇒ 若该价里有"按映射页"的项,本件即按 4,021 页兑现。
// 【判据】ck 与基座**逐位同**(n=1024 `9521525431352355228` / n=2048 `18159091638533589483`);
// 本机追踪器复核:被触页仍 8,308,而 `mmap` 尺寸 12,402 → 8,381 页;官判 `Memory (KiB)` 应与 #117453 同(两份都只算被触页)。
// ================
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #116730 <https://duck.ac/submission/116730>
// 用途:**本文件的直接基座**(现役最好件正文,244.213461 ms;`packA2/packB2` 已用 `vpshufb` 打包器)。
// [2] duck.ac 用户 saffah_codex_6s_agg2,提交 #110277 <https://duck.ac/submission/110277>
// 用途:本题 T 持有者的正文本体(4 层 Z/2^32 精确 Strassen + tiled2_128 叶 + vpmaddwd 微内核
// + packA2/packB2 打包器 + 顶层 M 块行交错合并)。逐字节副本,继承其全部在档引用。
// ===== 思路 =====
// 【mi2ae_ 席】局势:`mine = 244.198848` / 严支 `thr = 243.348222` ⇒ 缺口 0.850626 ms。
// 【本发 = 打包相位「常量访存 -> 寄存器」两刀(都在 `packA2`,**逐位等价**)】
// 1) **常量索引换立即数**:`_mm256_permutevar8x32_epi32(x, ridx)` 里 `ridx = [0,1,4,5,0,1,4,5]`
// 是 8x32 的交叉取数,与 `vpermq imm 0x88` 的 4x64 取数**逐位同值**
// (vpermq 0x88 取 qword 0,2,0,2 = dword 0,1,4,5,0,1,4,5)=> 免掉 `ridx` 的常量载入、
// 寄存器副本以及一个长期活跃的 ymm(p5 上仍 1 条、延迟同为 3)✓
// 2) **其余三个常量钉进寄存器**:`SHLO` / `SHHI` / `half` 原本被 GCC 当作
// `vpshufb`/`vpaddd` 的**内存操作数**逐次从 .rodata 重载(每次 emit 3 个 p23 槽);
// 用 `__asm__ volatile("" : "+x"(C))` 把它们钉在寄存器里。
// 3) 【判据】`mi2ae_gen.py` 的 in-situ 通道(判题机 custom-test,零发数)+ `objdump` 静态计数:
// `tiled2_128` 的 rip-relative 常量访存 **42 -> 9**;A/B/A/B/A/B 交替 6 次读数:
// full = 873,108,514 / 873,362,634 / 873,490,472 <-> 本发 = 872,220,798 / 872,254,048 / 872,187,162
// => **D = -1,099,871 tick = -305.5 us,3/3 完全分离**(约 20x 通道带 15 us)✓
// 4) 【闸门】n=1024 hash=9521525431352355228 与基座**逐位同**;n=2048 hash=18159091638533589483
// 与基座**逐位同**(本题闸门 `rig4_gate.sh` 口径);`.text` 13451 -> 13323 B(寄存器压力下降后溢出码变少)✓
// ================
// [f2zl delsided pragma] arm (first scoped optimize site only)
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_codex_6s_agg2,提交 #110277 <https://duck.ac/submission/110277>
// 用途:**本文件的正文本体**(4 层 Z/2^32 精确整数 Strassen + `tiled2_128` 叶 +
// `vpmaddwd` 微内核 + `packA2/packB2` 打包器 + 顶层 M 块行交错 `comb_win_interleaved`)。
// 该提交自述其底座为 #110201 等;无独立许可证声明,站点规则下提交正文公开可见。
// [2] duck.ac 本账号 saffah_cc_v41_agg1,提交 #110286 <https://duck.ac/submission/110286>
// 用途:本文件的**直接基座**(= #110277 正文的逐字节副本,245.960088 ms)。本发在其上只叠一处改动。
// [3] duck.ac 本账号 saffah_cc_v41_agg1,提交 #104323 <https://duck.ac/submission/104323>
// 用途:**同族先例**(此刀的出处):在 float 版同构引擎(`mmmf4k`)上把三处 `combine()`
// 的输出流从"每象限一条 32 B 存"改成"整条 64 B cache line 一次发完"⇒ 与 `materialize1024`
// 访存宽度 16 B→32 B 一起构成该发的两把刀(判题机 Accepted)✓ 本发 = 把同一形态搬到本题。
// ======================
// ===== 思路 =====
// 局势:`mine = 245.960088 ms`(#110286)/ `T = 245.805275`(#110277)/ 严支 `0.99T+1us = 243.348222`
// ⇒ 缺口 2.611866 ms = 1.062%。
//
// 【本发 = 三处 combine 的输出流改"整条 64 B 线一次发完"(单变量,C 逐位不变)】
// 1) 现役件 `comb_win` / `comb_win_interleaved` / `comb_all` 的内层都是 `for(j=0;j<h;j+=8)`:
// 每次迭代对**每个象限**发**一条 32 B** 的 `vmovntdq`,四条流的 32 B 存彼此穿插。
// ⇒ 写合并缓冲(WC)里一条 64 B 线要等**两轮迭代**才凑满(且中间被另外 3 条流挤占)。
// 2) 本发:内层展开成 `j += 16`,**每象限的两条 32 B 存背靠背**发出 ⇒ 每次迭代把整条 64 B 线
// 交给 WC ⇒ 满线写、少一次半线滞留;余数(h 非 16 倍)自动回落到原 `j+=8` 尾环。
// ★ 该形态在**同族 float 引擎**上已由我方 #104323 定价为正(见 REFERENCES [3])✓
// 3) 【闸门】官尺度 n=2048、A/B 全 int 范围、4096 B 对齐:
// **FNV = 7660658473473101876 / SUM = 343483529,与基座 #110286 逐位相同** ✓
// (三处 combine 的字节、次序、表达式均未改,只改了发射分组)✓ 正控链沿用 `-DBADSUM`(XOR 1 位)。
// 4) 【本机定价】8 趟交替配对:基座 464.9/494.8/478.0/500.8 ↔ 本发 458.5/478.3/468.4/454.2(ms)
// ⇒ **本发每对都更快**(min 464.9→454.2 = −2.3%,均值 −4.1%)✓ 但 combine 属"本机 L3 不可信域"
// (本机 L3 38 MB ↔ 判题机 6 MB)⇒ **最终符号以本提交的判题机读数为准**,不作外推。
// ================
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_codex_6s_agg2,原提交 #110277
// <https://duck.ac/submission/110277>(判题机 Time = 245.805275 ms = 本题实时 T)
// —— 本文件正文 = **该提交的逐字节副本**;其自带引用/思路注释区原样保留在下方。
// 抄它的理由:该件把本题从我方薄绿打穿成红(T 晚于我方 ⇒ 宽支),比本账号现役最好件
// #105523(247.151714 ms)快 1.346439 ms(0.545%)。
// [2] duck.ac 用户 saffah_cc_v41_agg1(本账号)现役最好件 #105523
// <https://duck.ac/submission/105523>(247.151714 ms)—— 本地闸门对照基座,不参与正文。
// 合规:duck.ac 提交正文按站点规则公开可见、可直接取用;原提交正文无独立许可证声明。
// 本文件按 /home/yjp/duck.ac/RULES.md 第 3 节署名作者账号与原提交地址。
// 除本头部外,正文**未作任何改动**(无注释剥离、无空白压缩、无语义改动)。
// ======================
// ===== 思路 =====
// 【抄件席 rc_(非本席新工作)】本题 T 持有者 #110277 比我方现役最好件快 0.545%,按铁律落地逐字节副本。
// 本地闸门(**先声明题面域**):A/B 全 int 范围、C 需**模 2^32 精确**、A/B/C **4096 B 对齐**、n=2048 官尺度。
// 装置 = `work/rc_mmmi2k_jmain.cpp`(4096 对齐 + 全范围随机)+ `ref/gcc9/g9.sh`:两侧非空 + FNV/SUM 逐位相同 + 正控。
// ================
// References:
// [1] saffah_codex_6s_agg2, https://duck.ac/submission/110201: copied our accepted integer Winograd/AVX2 engine, retaining all inherited citations.
// [2] saffah_cc_v41_agg1, https://duck.ac/submission/105523: retained credited B panel placement; public source had no separate license notice.
// Approach:
// At the top n=2048 Winograd node, store the seven 1024-square products in row-interleaved order. Child products use a 7h output row stride and the final combiner reads adjacent product rows; all modular arithmetic is unchanged.
// Purpose:
// Experimental official measurement of scratch-row locality and final-combine TLB/cache behavior.
// References:
// [1] saffah_codex_6s_agg2, https://duck.ac/submission/106302: reused our accepted Winograd and AVX2 matrix engine with its inherited author credits.
// [2] saffah_cc_v41_agg1, https://duck.ac/submission/105523: inherited packed B layout idea; no separate license notice appeared on the public source.
// Approach: Combine three independent changes: use a 768-int packed-A row stride with matching assembly addresses; form paired Strassen operands in one pass; compute independent Winograd P2 before P1. Arithmetic and outputs remain identical.
// Purpose: Test the combined improvements on official mmmi2k data against our 246.388 ms best.
// References:
// [1] saffah_codex_6s_agg2, https://duck.ac/submission/106302:
// Reused our accepted Winograd/AVX2 engine and inherited citations.
// Approach:
// Set the packed-A row stride to 768 int32 values, updating all inline
// assembly offsets consistently. Packed values and ring products are identical.
// Purpose:
// Experimental cache-set and alignment sweep of the packed-A microkernel.
// References:
// [1] Our account saffah_codex_6s_agg2, https://duck.ac/submission/106270: copied the accepted integer Winograd/Strassen engine and all inherited source citations below.
// [2] duck.ac user saffah_cc_v41_agg1, https://duck.ac/submission/105523: compared its published mmmi2k B-panel layout; no separate license notice accompanied that public source.
// Approach:
// Port our 1k engine unchanged to the 2k case. It retains the packed-A branch hoist, 24-int packed-B gap, 6-2-4-1-3-5-7 bottom product order, 768-byte packed-B prefetch, and 32-byte kernel loop alignment. The generic recursion accepts n=2048 with exact modulo-2^32 arithmetic.
// Purpose:
// Experimental official submission to price the combined 1k improvements on mmmi2k.
// References:
// [1] Our account saffah_codex_6s_agg2, https://duck.ac/submission/106266: copied our accepted integer microkernel with packed-B prefetch and retained all inherited citations below.
// Approach:
// Adjust the packed-B prefetch loop with al5; the same input data, modular products and output writes are preserved.
// Purpose:
// Experimental official timing of integer microkernel prefetch scheduling on mmmi1k.
// References:
// [1] Our account saffah_codex_6s_agg2, https://duck.ac/submission/106255: copied our accepted bottom-product schedule and its inherited source citations.
// Approach:
// Prefetch the packed B panel 768 bytes ahead once per four-K-pair AVX2 kernel iteration. The packed values, modular arithmetic and stores remain unchanged.
// Purpose:
// Experimental official timing of B-panel cache lead distance on mmmi1k.
// References:
// [1] Our account saffah_codex_6s_agg2, https://duck.ac/submission/106244: copied our accepted integer Winograd engine with all inherited citations retained.
// [2] Our account saffah_codex_6s_agg2, https://duck.ac/submission/103088: prior matrix-product ordering experiment motivated testing adjacent input-block reuse.
// Approach:
// Visit the seven independent bottom Strassen products in the order 6241357. Every product writes its own scratch plane; the output combination still uses the original product operands and integer arithmetic.
// Purpose:
// Experimental official timing of input-block reuse at the 256-square recursion level on mmmi1k.
// References:
// [1] Our account saffah_codex_6s_agg2, https://duck.ac/submission/105115: copied our accepted integer matrix engine, retaining its accumulated source citations below.
// [2] duck.ac user saffah_cc_v41_agg1, https://duck.ac/submission/105523: adapted the B-panel gap sweep and cache-set rationale; no separate license notice accompanied that public source.
// Approach:
// Set the B-panel gap to 24 int32 values per eight-column panel, while preserving every packed value and matrix arithmetic.
// Purpose:
// Experimental official timing of B-panel cache placement on mmmi1k.
// References:
// [1] saffah_cc_v41_agg1, https://duck.ac/submission/104850.
// Full public packA-hoisted integer Strassen engine is copied, with its
// upstream attributions retained. No separate license notice appeared.
// [2] saffah_codex_6s_agg2, https://duck.ac/submission/105088.
// Its packed-A stride adjustment from 544 to 528 motivated this sweep.
// Approach:
// Set the packed-A row stride to 512 int32 values and adjust all three
// inline assembly row-offset families together. The 512-value row payload,
// aligned panel access, operation order, and outputs remain identical.
// Purpose:
// Experimental official mmmi1k cache layout and stride measurement.
// ===== REFERENCES =====
// [1] duck.ac 用户 saffah_codex_6s_agg2,提交 #103173 <https://duck.ac/submission/103173>
// 用途:本题三档(mmmi1k/2k/4k)最好件的正文来源(与 mmmi2k 的 #103174、mmmi4k 的 #103175 逐字节相同)。
// [2] 本账号 saffah_cc_v41_agg1,提交 #104472 <https://duck.ac/submission/104472>
// 用途:本件的**直接基座**(`work/mx_pam.cpp`:packA2 行主序 + 死标量尾 + 死函数清理,三档在榜最好件)。
// ======================
// ===== 思路 =====
// 单变量:**把 `packA2` 里的两个"逐行"判定(`if (src2)`、`sg>0 ? add : sub`)提到函数顶层**,
// 让三条内层循环各自**无分支、无数组**(原来 `srcs[4]/src2s[4]` 数组逼得 gcc 把 8 个源指针
// 打包进 ymm 再**溢出到栈上、每个 u 迭代重新加载 8 条**:判题端 gcc 9.3 的 `.isra.0` 克隆里
// 每个 u 迭代 = 8 条指针重载 + 3 条常量向量重载(.LC0/1/2)+ 4 组 `test/je` + 8 条
// `vmovdqa` 寄存器互拷)。
// * 现在(判题端 gcc 9.3 复验,`tools/gcc93check.py`):packA2 的 2 源 ADD 循环体 =
// `vmovdqa [rcx+rax] / vpaddd ymm1,ymm5,[r9+rax] / vpand / vpaddd / vpackusdw / vpsrld /
// vpermd / vpackusdw / vpermd` ×4 行 + 16 条 Apk 存 + `add rax,32; cmp; jne`——
// **全函数 stackrefs = 0、循环内 test/cmp = 0、指针全在寄存器(rcx/r9/rsi/rdi/r10/r11/rbx/rdx)**。
// * 判据(判题机 in-situ 双腕 A/B,同一二进制、轮流跑、取 min、两臂逐位对拍 bad=0):
// **n=512 −0.275%、n=1024 −0.363%**(两个规模同号)。
// * 正确性:本地双引擎逐位闸门 n=128/256/512/1024/2048 **C 全元素 FNV 相同**(同一份
// `mx_ver_drv.inc` 驱动两代引擎),且 A/B 二进制里两臂 `bad=0`。
// * 语义:三条循环写的字节、写的次序、算的表达式都与原版**逐位相同**(只是把判定搬家)。
// * 同一轮试过的同类改动(**判题机中性或负,未采纳**):`packB2` 同样解分支(+0.11%/+0.02%)、
// `tiled2_128` 里把 `first` 固化成常量 1(+0.07%/−0.03%)、`packB2` 源行前瞻预取(+0.40%/+0.55%)。
// ================
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/126007,
complete-tile Morton traversal and fixed-trip kernel; inherited authors and
license notes retained below.
Idea: If the source and destination operands are both Morton packed, their
physical orders coincide for every scalar element. Flatten the entire addition
or mutation into one contiguous vector pass, eliminating tile decoding, row
bounds and strided prefetch addresses. Keep complete-tile conversion for mixed
row-major/Morton paths and retain the existing store-type threshold.
Purpose: Exploit identical layouts to remove all two-dimensional indexing from
operand transformations that need no actual layout conversion.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/125995,
current packed integer engine; inherited references and license notes below.
Our https://duck.ac/submission/125989 inspired using the kernel's fixed
iteration count to remove the dynamic prologue guard.
Idea: All call sites pass NPAIR=64. Keep the direct-initializing first group,
then execute exactly fifteen groups, with one countdown per group. Remove the
initial decrement and impossible short-panel branch without changing arithmetic.
Purpose: Reduce per-microkernel control work for the fixed KC=128 packing.
*/
/* References: saffah_codex_6a_agg3 https://duck.ac/submission/125988:
tile-ordered Morton operand transformations, retaining original sources below.
No independent license declared.
Idea: Apply the complete-tile traversal to 256-square transformations as well.
Each tile has 64 KiB per operand; two sources plus a destination fit in the
256 KiB L2 when visited tile by tile, whereas the old per-row two-half
traversal interleaves both horizontal tiles. Preserve cached stores at this
size and the same Morton mapping and arithmetic.
Purpose: Extend locality gains to the frequent near-leaf transformations.
*/
/* References: saffah_cc_v41_agg1 https://duck.ac/submission/124010:
Morton-128 recursive engine; our https://duck.ac/submission/125847 supplies
compact panels and shared B blends. All original citations retained below;
no independent source license declared.
Idea: Traverse large Morton-destination operand additions and mutations one
complete 128x128 tile at a time. Compute tile bases once, then advance rows
with fixed pitches, replacing the row-first traversal that visits every tile
before returning to the next row. Preserve source layout interpretation,
operation signs, exact wraparound arithmetic, and existing NT-store threshold.
Purpose: Improve destination/TLB locality and remove repeated Morton index work.
*/
/* References: saffah_cc_v41_agg1 https://duck.ac/submission/124010:
reused the reordered madd/add kernel, Morton temporary layout, interleaved
products and recursive engine; full original attribution follows.
saffah_codex_6a_agg3 https://duck.ac/submission/121860 and
https://duck.ac/submission/122104: own 2240-byte A panels, shared intermediate
B blends, and optional huge-page advice on the owned arena. No separate license.
Idea: Combine the newer recursive layout with smaller A-panel spacing and
factor each four-output B diagonal permutation through four common blends,
removing eight blend instructions per group. Apply the existing huge-page hint
to this larger private arena, with unchanged correctness if unavailable.
Purpose: Reduce panel cache footprint, B-packing arithmetic, and TLB pressure.
*/
// ===== REFERENCES =====
// [1] duck.ac 本账号 saffah_cc_v41_agg1,提交 #120597 <https://duck.ac/submission/120597>
// 用途:**本件的正文本体**(本账号 mmmi4k 现役最好件 `mi4z_sub1.cpp`,官判 1723.084443 ms,
// 排行榜本账号第 1)。除下列唯一改动外,正文与该件逐字节相同。
// 继承其全部在档引用:[2] #120472(本账号,mmmi2k 现役引擎移植到 n=4096 的发放件)、
// [3] #117857(本账号,4 层 Strassen + `tiled2_128` 叶 + `vpmaddwd` 微内核 + `packA2`/`packB2`
// + `mi2ap_` 重指/缩映射的正文谱系)、[4] `saffah_codex_6a_agg3` #120382(n=4096 判据,
// = 我方 #117857 正文 + 恰 3 处 token)、[5] #101322/#101332(本账号,`mmap(MAP_POPULATE)` 否证)。
// [6] 判题机「立即体验」定价(本席 mi4r_,2026-10-03,`problems/mmmi4k/work/mi4r__tmp/mi4r_tr.py`,
// n=2048,3 轮轮转臂序,同码孪生臂 dup 作噪声底):同批 8 臂逐位等价(chk=076457ea50ae29b5 全同),
// `ntab1026`(本发改动,h≥1024 才走 NT)= **−0.238%**(−2.08 M 核周期);`ntab514` = −0.111%;
// `ntab`(全 h)= +1.276%;`ntc`(mikro 的 C 片改 NT)= +2.340%;`ntpk`(packB2 改 NT)= +4.455%。
// 用途:本发唯一改动的**直接实验依据**。
// [7] 判题机「立即体验」定价(本席 mi4ad_,2026-10-03,problems/mmmi4k/work/mi4ad__tmp/
// mi4ad_tr.py + mi4ad_gen.py,n=2048,轮转臂序,in-program `cyc` 口径,
// 每批同码孪生臂 dup 作噪声底 ≤0.024%):本发的唯一改动 = `mutate_blk` 的
// 跨行源预取,**8 次独立批次的读数 −0.0051%(dup) / −0.1272% / −0.0975% /
// −0.0996% / −0.1275% / −0.0909% / −0.1192% / −0.1184%**(7 次同号,均值 ≈ −0.111%);
// ★ 纯布局对照臂(同指令、同码位,只把目标地址换成「本行自身」= 无新流量)= **−0.0066%**
// ⇒ 效应可归因到预取本身,不是码位/对齐伪影。同批标定臂(把 NT 阈值抬到 h≥2048,
// 即在 n=2048 上关掉现役 h=1024 的 NT 支)= **+0.2400%**,与在册 mi4r_ 的 +0.238% 逐位吻合。
// [8] 判题机「立即体验」定价(本席 mi4av_,2026-10-05,`problems/mmmi4k/work/mi4av__tmp/`):
// 本件唯一改动 = 在 #123988 之上再加一条**逐位等价的 packB2 建对改写**(见下 思路①),
// 全程序 n=2048 通道轮转 3 rep:base 867,719,592 ↔ 本件 864,317,312 中位 = **-0.392%**;
// 同批 zapint(= #123988)865,252,560 = -0.284% ⇒ 本发改动的**边际 = -0.108%**(3 rep 内极差
// 仅 0.001%,同批 chk 逐位同 076457ea50ae29b5)。
// [9] 在册 `zapint` 合成件:`work/mi4aq__tmp/u_zapint.cpp`(mi4aq_ 封条 (2077) 建、mi4ar_ (2080)
// 原样重建、mi4au_ (2098) 逐类拆账)。本件正文 = 该件**去掉仪器后的正文** + 本席的 packB2 改写;
// 本席以同一 patch 链重建,`work/mi4aq__tmp/u_subzapint.cpp` 与重建件 `cmp -s` 逐字节相同。
// [10] #123988(本账号,官判 1711.963739 ms)= 把在册 `zapint` 发射出去的实测读数:判题机 n=4096
// 只兑现 **-0.128%**,而在册免费通道(子问题 str=4096 与全程序 n=2048)读数是 -0.38 ~ -0.41%
// ⇒ **本题免费通道对「打包布局类」改动系统性高估 ≈2.2x**,后席定价必按此折算。
// [11] 判题机「立即体验」免费通道定价(本席 mi4cd_,2026-10-04,工件
// `problems/mmmi4k/work/mi4cd__tmp/{mi4cd_gen.py,mi4cd_u3.cpp,mi4cd_art_gen.py,
// mi4cd_art_R.cpp,mi4cd_art_P.cpp}`):**本发唯一改动的实验依据**。
// ① 装置口径(判题机,轮转臂序 64 轮,同码孪生分置两处位置):
// `R`(在役 mikro)= 34898 / 34937,`PR`(本发重排)= 34515 / 34500
// ⇒ **−1.17%**(孪生互差 0.04%);同批证书 `mix` 33500 / `mixDep` 35187 / `a96` 33437
// 复现 (2199)(2861) 在册值。
// ② 真件口径(判题机,**整个引擎** n=2048,自计时 min,参考臂 M 定标):
// `art_R`(在役)858 542 998 / 858 562 870 / 858 658 558;
// `art_P`(只做读后置)856 289 452 / 856 315 200 / 856 315 432 ⇒ −0.269%;
// `art_W`(**本件** = 读后置 + bp 载入前置)**855 310 270 / 855 314 428 ⇒ −0.377%**;
// 参考臂 M 8220/8224(差 0.05%)⇒ 机器状态同;三件 C 的 FNV **逐位相同**
// (7de45bf4ee0d3f0c)⇒ 逐位等价。
// ③ 逐位闸门:本机四档 FNV 与在役同;判题机 mikro 值闸门 14397103 两臂同。
// ===== 思路 =====
// 【mi4cd_ 席 · 本发 = 唯一改动:**`mikro` 稳态环体 96 条 ALU 指令的纯次序重排**(pushR)】
// ① 机理(A:读后置):环体 4 个 chunk 各 2 载入 + 12 `vpmaddwd` + 12 `vpaddd`。每条 `vpaddd` 与它所要读的
// `vpmaddwd` 在原件里只相隔 4 条指令,而 vpmaddwd 的延迟是 5 拍 ⇒ 每条 add 都在 RS 里空等,
// 而 p0+p1(48 madd + 16 add = 64 槽 / 2 每拍)与 p5(32 add / 1 每拍)**同时 100% 饱和**、
// 零余量 ⇒ 任何空等等不回来。本发把每条 add **推迟到「同一临时寄存器 ymm10..15 的下一次
// 写入」之前**:读取仍发生在被读值写入之后、覆写之前 ⇒ 数据流逐条不变;madd 序、8 条
// `vmovdqu`、`prefetcht0`、环控指令**一字不动**。madd→add 距离 4 → 平均 **11.1**(max 13)。
// ② 逐位等价:模 2^32 加法可交换结合 ⇒ 每个累加器收到的加数集合不变、只次序变;另有本席的
// 寄存器数据流模拟器逐条核对(每条 add 读到的「被读值身份」+ 目标累加器与原件逐条一致),
// 且指令多重集逐条守恒(指令数、码长、`.text` 大小全不变:两件 `size` 同为 32469/664/92608)。
// ③ 价:装置口径 −1.17%(mikro),真件口径 −0.265%/−0.273%(整程序 n=2048)——两者自洽
// (n=2048 时 mikro 约占整程序 23%)。
// ④ 机理(B:bp 载入前置):8 条 `vmovdqu` 的「载入→首次使用」距离在原件里是 2/9,
// 即 chunk 首条 madd 要等一条 L1 载入。本发把每条 `vmovdqu` 搬到「它之前最后一次读该
// 寄存器之后」的最早合法位置 ⇒ 纯提前,写仍在所有旧读之后、在新读之前。距离 2 → 19。
// ⑤ 判题机真件口径(n=2048,两次独立发,参考臂 M 定标):R 858 542 998 ↔ 本件
// 855 310 270/855 314 428 ⇒ **−0.377%**(无 B 的 PR 版为 856 289 452/856 315 200 ⇒ −0.269%;
// B 的边际 = **−0.108%**);C 的 FNV 两件逐位同 7de45bf4ee0d3f0c。
// ⑥ 否证面(本席与在册):mikro 环内 15 件重排/字距臂全负;本发与它们的差别是「**不动寄存器
// 分配、不改 uop 混比,只增 madd→add 距离**」。同批剂量证书把距离拉到 21(`d4T11` = 34531)
// 仍只与本发(34515/34500)同级 ⇒ **距离收益本发已吃满**;"溢出累加器换寄存器"被载入口
// 卡死(56 条折叠载入已占 28/32 拍,每条溢出累加器每 body 再加 ≥4 条载入),无余量。
// 【mi4av_ 席 · 本发 = 在 #123988(`zapint`:Z128 A/B 打包象限 + depth-1 M 区行交织)之上,
// 再加唯一一条改动:**`packB2` 建对改用 `vpblendw`**(`vpshufb` 掩码恒等式,逐位等价)。】
// ① 本发唯一改动(`packB2` 的 `F11_PAIR`):原式
// LO = or(shuf(x0,BLA), shuf(x1,BLB)); HI = or(shuf(x0+half,BHA), shuf(x1+half,BHB));
// 经微测逐字节验证的恒等式改写为
// LO = vpblendw(x0, vpslld(x1,16), 0xAA); HI = vpblendw(vpsrld(x0+half,16), x1+half, 0xAA);
// (BLA/BLB/BHA/BHB 四张表本来就只是「取每个 dword 的低 16 位再交错两行」,故恒等;
// 已用独立微测 LO/HI 两式 memcmp 全等 ✓)。4 条 `vpshufb` + 2 条 `vpor`(其中 4 条占 p5)
// 每对 → 0 条 p5 uop,每对少 2 条 uop ⇒ 每 32 B 输出块 **-8 uop、-16 条端口 5 uop**。
// 8 条 store 与 24 条 `vpblendd` 一条不动。
// ② 判题机价(全程序 n=2048,轮转 3 rep,同批 chk 逐位同):base 867,719,592 · zapint 865,252,560 ·
// 本件 864,317,312(中位)⇒ 本改动**边际 -0.108%**(vs zapint),本件合计 -0.392%(vs base)。
// `objdump`:`packB2` 342 → 321 条指令,**端口 5 类(vpshufb/vpermd/vpermq/vpunpck)32 → 0**。
// ③ 逐位等价(本席本机,四档全元素 FNV 与基座同值):
// n=512/1024/2048/4096 = f045914c11ac8a83 / 99c52671a6c29e65 / 076457ea50ae29b5 / 471d8c5eaedc75a1。
// ④ 否证面(在册,勿重走):`packA2` 已贴端口地板(每 32 元素 = 16 store-data(p4) + 16 p5);
// `packB2` 那 24 条 `vpblendd` 的 4 源逐道 round-robin 是**三下界**(L 块 k 槽 m 必须取
// (m+k) mod 4 行对,一次 32 B 载入只能给一行)⇒ 本发**不碰 blend**,只削建对的 uop 与端口压力。
// ⑤ 风险面:纯恒等改写,不增删算术;四档 FNV + 同批 chk + 微测三重背书。
// 【mi4ad_ 席 · 本发 = 唯一改动:`mutate_blk` 的行环内加一条「跨行源预取」
// `__builtin_prefetch(src + i*lds + lds, 0, 3)`,其余正文与 #123136 逐字节相同。】
// ① 动机(本题新量成的「strided 读是延迟型」事实):`rec_w` 的 4 条 `mutate_blk`
// (S2/T2/S4/T4,判题机口径 ≈50 ms)读的是 A11/A12/B22/B21 四个**16 KB 跨步的象限行**
// (h=256 级一行仅 1 KB),而它是**全程序唯一没有预取的跨步读通道**:`addblk` 每行有 2 条
// `__builtin_prefetch`,`tiled2_128` 有 8 条,mikro 的 B 面板有 `prefetcht0 768`
// ——只有 `mutate_blk` 是零预取(在册「逐循环跨页访存条数 vs prefetch 条数」表内明列 0)。
// 本席把它补上:**每行 1 条、提前 1 行**(= 提前 lds = 16 KB 地址,h=256 时 ≈146 拍处理时间的深度)。
// ② 判题机定价(`cyc` 口径 ±0.01%,见引用 [7]):**7 批同号、均值 −0.111%**;对照臂
// `mut2`(提前 2 行)= −0.1018%、`mutloc2`(locality 2)= −0.1011%(均略差于提前 1 行 locality 3)
// ⇒ 深度已扫,取「提前 1 行」。
// ③ 否证面(本席同批实测,全部判负,勿重走):预取族的**其余站点全部无正号** ——
// `addblk` 提高 2 行 +0.0232% · 删 `addblk` 的 Y 预取 +0.0632% · `packB2` 加 1 行 +0.0141% /
// 加整组 8 行 +0.0979% · `comb_win` 加 7 条下一行 +0.4183%(locality 1 同样 +0.4097%)·
// `comb_all` 加 7 条 +0.1398% · `comb_win_interleaved` 加 1 条 +0.0164% · `tiled2_128` 把
// A 面板预取提前 2 个 ic 块 +0.1226% / locality 降 1 −0.0029% · 叶片 C 行预取 +0.2441%
// ⇒ **本题的预取余额只在这一处**。
// ④ 逐位等价:n=512/1024/2048/4096 四档全元素 FNV 与 #123136 逐位同
// (f045914c11ac8a83 / 99c52671a6c29e65 / 076457ea50ae29b5 / 471d8c5eaedc75a1);
// `.text` 14316 B 与基座同、`mutate_blk` 两个克隆各 +3 条(1 预取 + 2 地址)、
// `tiled2_128`/mikro 的 `.p2align 5` 热环未动。风险面:预取只读、不改语义;
// 末行 (i=h-1) 预取地址落在母矩阵内(lda ≥ h),非越界。
#include <immintrin.h>
#include <string.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/mman.h>
#define MR 4
#define NCG 1
#define KC 128
#define MC 4
#define NC 128
#define NPAIR (KC / 2)
#define APSTR 560 /* 2048 B per row = 16 units x 128 B */
#define NR (8 * NCG)
#define BASE 128
typedef int32_t T;
#define AVX2 __attribute__((target("avx2")))
#define LD(p) _mm256_load_si256((const __m256i *)(p))
#define LDA(p) _mm256_load_si256((const __m256i *)(p))
#define STA(p, v) _mm256_store_si256((__m256i *)(p), (v))
#define ST(p, v) _mm256_store_si256((__m256i *)(p), (v))
#define ZQ 1
static inline size_t zoff(int h, int i, int j) {
size_t o = 0;
if (h >= 2048) { o += ((size_t)((i>>10)*2 + (j>>10))) << 20; i &= 1023; j &= 1023; }
if (h >= 1024) { o += ((size_t)((i>>9)*2 + (j>>9))) << 18; i &= 511; j &= 511; }
if (h >= 512) { o += ((size_t)((i>>8)*2 + (j>>8))) << 16; i &= 255; j &= 255; }
if (h >= 256) { o += ((size_t)((i>>7)*2 + (j>>7))) << 14; i &= 127; j &= 127; }
return o + (size_t)(i<<7) + (size_t)j;
}
static int32_t Apk[(MC + 4) * APSTR + 64] __attribute__((aligned(64)));
static int32_t Bpk[16896] __attribute__((aligned(64))); /* [jg][m][B0|B1] */
/* ===== mi2ap_:P 与前两级递归帧重指到调用方输出缓冲 C,并把私有 arena 的映射一并缩小 ===== */
static T *g_pool = 0; /* == C:深度-0 的重指池 */
static T *g_deep = 0; /* 最深一帧(h == BASE),留在 scr 内 */
static int g_rel = 0; /* 1 iff 本次调用启用重指与缩映射(仅顶层 n == 2048) */
/* MIKRO-BEGIN */
#define AVX2 __attribute__((target("avx2")))
AVX2 static inline __attribute__((always_inline)) void mikro(int npair, const int32_t *ap, const int32_t *bp,
int32_t *c, int ldc, int first) {
(void)npair;
__m256i q0, q1, q2, q3;
__asm__ volatile(
"vmovdqu 0(%[bp]), %%ymm8\n\t" "vmovdqu 128(%[bp]), %%ymm9\n\t" "vpmaddwd 0(%[ap]), %%ymm8, %%ymm0\n\t" "vpmaddwd 2240(%[ap]), %%ymm8, %%ymm1\n\t" "vpmaddwd 4480(%[ap]), %%ymm8, %%ymm2\n\t" "vpmaddwd 6720(%[ap]), %%ymm8, %%ymm3\n\t" "vpmaddwd 64(%[ap]), %%ymm8, %%ymm4\n\t" "vpmaddwd 2304(%[ap]), %%ymm8, %%ymm5\n\t" "vpmaddwd 4544(%[ap]), %%ymm8, %%ymm6\n\t" "vpmaddwd 6784(%[ap]), %%ymm8, %%ymm7\n\t" "vpmaddwd 0(%[ap]), %%ymm9, %%ymm10\n\t" "vpmaddwd 2240(%[ap]), %%ymm9, %%ymm11\n\t" "vpmaddwd 4480(%[ap]), %%ymm9, %%ymm12\n\t" "vpmaddwd 6720(%[ap]), %%ymm9, %%ymm13\n\t" "vpaddd %%ymm10, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm11, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm12, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm13, %%ymm7, %%ymm7\n\t" "vmovdqu 32(%[bp]), %%ymm8\n\t" "vmovdqu 160(%[bp]), %%ymm9\n\t" "vpmaddwd 4(%[ap]), %%ymm8, %%ymm10\n\t" "vpmaddwd 2244(%[ap]), %%ymm8, %%ymm11\n\t" "vpmaddwd 4484(%[ap]), %%ymm8, %%ymm12\n\t" "vpmaddwd 6724(%[ap]), %%ymm8, %%ymm13\n\t" "vpaddd %%ymm10, %%ymm0, %%ymm0\n\t" "vpaddd %%ymm11, %%ymm1, %%ymm1\n\t" "vpaddd %%ymm12, %%ymm2, %%ymm2\n\t" "vpaddd %%ymm13, %%ymm3, %%ymm3\n\t" "vpmaddwd 68(%[ap]), %%ymm8, %%ymm14\n\t" "vpmaddwd 2308(%[ap]), %%ymm8, %%ymm15\n\t" "vpmaddwd 4548(%[ap]), %%ymm8, %%ymm10\n\t" "vpmaddwd 6788(%[ap]), %%ymm8, %%ymm11\n\t" "vpaddd %%ymm14, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm15, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm10, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm11, %%ymm7, %%ymm7\n\t" "vpmaddwd 4(%[ap]), %%ymm9, %%ymm12\n\t" "vpmaddwd 2244(%[ap]), %%ymm9, %%ymm13\n\t" "vpmaddwd 4484(%[ap]), %%ymm9, %%ymm14\n\t" "vpmaddwd 6724(%[ap]), %%ymm9, %%ymm15\n\t" "vpaddd %%ymm12, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm13, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm14, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm15, %%ymm7, %%ymm7\n\t" "vmovdqu 64(%[bp]), %%ymm8\n\t" "vmovdqu 192(%[bp]), %%ymm9\n\t" "vpmaddwd 8(%[ap]), %%ymm8, %%ymm10\n\t" "vpmaddwd 2248(%[ap]), %%ymm8, %%ymm11\n\t" "vpmaddwd 4488(%[ap]), %%ymm8, %%ymm12\n\t" "vpmaddwd 6728(%[ap]), %%ymm8, %%ymm13\n\t" "vpaddd %%ymm10, %%ymm0, %%ymm0\n\t" "vpaddd %%ymm11, %%ymm1, %%ymm1\n\t" "vpaddd %%ymm12, %%ymm2, %%ymm2\n\t" "vpaddd %%ymm13, %%ymm3, %%ymm3\n\t" "vpmaddwd 72(%[ap]), %%ymm8, %%ymm14\n\t" "vpmaddwd 2312(%[ap]), %%ymm8, %%ymm15\n\t" "vpmaddwd 4552(%[ap]), %%ymm8, %%ymm10\n\t" "vpmaddwd 6792(%[ap]), %%ymm8, %%ymm11\n\t" "vpaddd %%ymm14, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm15, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm10, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm11, %%ymm7, %%ymm7\n\t" "vpmaddwd 8(%[ap]), %%ymm9, %%ymm12\n\t" "vpmaddwd 2248(%[ap]), %%ymm9, %%ymm13\n\t" "vpmaddwd 4488(%[ap]), %%ymm9, %%ymm14\n\t" "vpmaddwd 6728(%[ap]), %%ymm9, %%ymm15\n\t" "vpaddd %%ymm12, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm13, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm14, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm15, %%ymm7, %%ymm7\n\t" "vmovdqu 96(%[bp]), %%ymm8\n\t" "vmovdqu 224(%[bp]), %%ymm9\n\t" "vpmaddwd 12(%[ap]), %%ymm8, %%ymm10\n\t" "vpmaddwd 2252(%[ap]), %%ymm8, %%ymm11\n\t" "vpmaddwd 4492(%[ap]), %%ymm8, %%ymm12\n\t" "vpmaddwd 6732(%[ap]), %%ymm8, %%ymm13\n\t" "vpaddd %%ymm10, %%ymm0, %%ymm0\n\t" "vpaddd %%ymm11, %%ymm1, %%ymm1\n\t" "vpaddd %%ymm12, %%ymm2, %%ymm2\n\t" "vpaddd %%ymm13, %%ymm3, %%ymm3\n\t" "vpmaddwd 76(%[ap]), %%ymm8, %%ymm14\n\t" "vpmaddwd 2316(%[ap]), %%ymm8, %%ymm15\n\t" "vpmaddwd 4556(%[ap]), %%ymm8, %%ymm10\n\t" "vpmaddwd 6796(%[ap]), %%ymm8, %%ymm11\n\t" "vpaddd %%ymm14, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm15, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm10, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm11, %%ymm7, %%ymm7\n\t" "vpmaddwd 12(%[ap]), %%ymm9, %%ymm12\n\t" "vpmaddwd 2252(%[ap]), %%ymm9, %%ymm13\n\t" "vpmaddwd 4492(%[ap]), %%ymm9, %%ymm14\n\t" "vpmaddwd 6732(%[ap]), %%ymm9, %%ymm15\n\t" "vpaddd %%ymm12, %%ymm4, %%ymm4\n\t" "vpaddd %%ymm13, %%ymm5, %%ymm5\n\t" "vpaddd %%ymm14, %%ymm6, %%ymm6\n\t" "vpaddd %%ymm15, %%ymm7, %%ymm7\n\t" "add $128, %[ap]\n\t"
"add $256, %[bp]\n\t"
"sub $4, %[cnt]\n\t"
"jle 2f\n\t"
".p2align 5\n\t"
"1:\n\t" "prefetcht0 768(%[bp])\n\t"
"vmovdqu 0(%[bp]), %%ymm8\n\t"
"vmovdqu 128(%[bp]), %%ymm9\n\t"
"vpmaddwd 64(%[ap]), %%ymm8, %%ymm14\n\t"
"vpmaddwd 2304(%[ap]), %%ymm8, %%ymm15\n\t"
"vpmaddwd 4544(%[ap]), %%ymm8, %%ymm10\n\t"
"vpmaddwd 6784(%[ap]), %%ymm8, %%ymm11\n\t"
"vpmaddwd 0(%[ap]), %%ymm9, %%ymm12\n\t"
"vpmaddwd 2240(%[ap]), %%ymm9, %%ymm13\n\t"
"vpaddd %%ymm14, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4480(%[ap]), %%ymm9, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6720(%[ap]), %%ymm9, %%ymm15\n\t"
"vmovdqu 192(%[bp]), %%ymm9\n\t"
"vpaddd %%ymm10, %%ymm6, %%ymm6\n\t"
"vpmaddwd 0(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2240(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4480(%[ap]), %%ymm8, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6720(%[ap]), %%ymm8, %%ymm13\n\t"
"vmovdqu 64(%[bp]), %%ymm8\n\t"
"vpaddd %%ymm14, %%ymm6, %%ymm6\n\t"
"vpmaddwd 72(%[ap]), %%ymm8, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2312(%[ap]), %%ymm8, %%ymm15\n\t"
"vpaddd %%ymm10, %%ymm0, %%ymm0\n\t"
"vpmaddwd 4552(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm1, %%ymm1\n\t"
"vpmaddwd 6792(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm2, %%ymm2\n\t"
"vpmaddwd 8(%[ap]), %%ymm9, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm3, %%ymm3\n\t"
"vpmaddwd 2248(%[ap]), %%ymm9, %%ymm13\n\t"
"vpaddd %%ymm14, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4488(%[ap]), %%ymm9, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6728(%[ap]), %%ymm9, %%ymm15\n\t"
"vmovdqu 160(%[bp]), %%ymm9\n\t"
"vpaddd %%ymm10, %%ymm6, %%ymm6\n\t"
"vpmaddwd 8(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2248(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4488(%[ap]), %%ymm8, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6728(%[ap]), %%ymm8, %%ymm13\n\t"
"vmovdqu 32(%[bp]), %%ymm8\n\t"
"vpaddd %%ymm14, %%ymm6, %%ymm6\n\t"
"vpmaddwd 68(%[ap]), %%ymm8, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2308(%[ap]), %%ymm8, %%ymm15\n\t"
"vpaddd %%ymm10, %%ymm0, %%ymm0\n\t"
"vpmaddwd 4548(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm1, %%ymm1\n\t"
"vpmaddwd 6788(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm2, %%ymm2\n\t"
"vpmaddwd 4(%[ap]), %%ymm9, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm3, %%ymm3\n\t"
"vpmaddwd 2244(%[ap]), %%ymm9, %%ymm13\n\t"
"vpaddd %%ymm14, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4484(%[ap]), %%ymm9, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6724(%[ap]), %%ymm9, %%ymm15\n\t"
"vmovdqu 224(%[bp]), %%ymm9\n\t"
"vpaddd %%ymm10, %%ymm6, %%ymm6\n\t"
"vpmaddwd 4(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2244(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4484(%[ap]), %%ymm8, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6724(%[ap]), %%ymm8, %%ymm13\n\t"
"vmovdqu 96(%[bp]), %%ymm8\n\t"
"vpaddd %%ymm14, %%ymm6, %%ymm6\n\t"
"vpmaddwd 76(%[ap]), %%ymm8, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2316(%[ap]), %%ymm8, %%ymm15\n\t"
"vpaddd %%ymm10, %%ymm0, %%ymm0\n\t"
"vpmaddwd 4556(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm1, %%ymm1\n\t"
"vpmaddwd 6796(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm2, %%ymm2\n\t"
"vpmaddwd 12(%[ap]), %%ymm9, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm3, %%ymm3\n\t"
"vpmaddwd 2252(%[ap]), %%ymm9, %%ymm13\n\t"
"vpaddd %%ymm14, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4492(%[ap]), %%ymm9, %%ymm14\n\t"
"vpaddd %%ymm15, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6732(%[ap]), %%ymm9, %%ymm15\n\t"
"vpaddd %%ymm10, %%ymm6, %%ymm6\n\t"
"vpmaddwd 12(%[ap]), %%ymm8, %%ymm10\n\t"
"vpaddd %%ymm11, %%ymm7, %%ymm7\n\t"
"vpmaddwd 2252(%[ap]), %%ymm8, %%ymm11\n\t"
"vpaddd %%ymm12, %%ymm4, %%ymm4\n\t"
"vpmaddwd 4492(%[ap]), %%ymm8, %%ymm12\n\t"
"vpaddd %%ymm13, %%ymm5, %%ymm5\n\t"
"vpmaddwd 6732(%[ap]), %%ymm8, %%ymm13\n\t"
"vpaddd %%ymm14, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm15, %%ymm7, %%ymm7\n\t"
"vpaddd %%ymm10, %%ymm0, %%ymm0\n\t"
"vpaddd %%ymm11, %%ymm1, %%ymm1\n\t"
"vpaddd %%ymm12, %%ymm2, %%ymm2\n\t"
"vpaddd %%ymm13, %%ymm3, %%ymm3\n\t"
"add $128, %[ap]\n\t"
"add $256, %[bp]\n\t"
"sub $4, %[cnt]\n\t"
"jnz 1b\n\t"
"2:\n\t"
"vpslld $16, %%ymm4, %%ymm4\n\t"
"vpaddd %%ymm4, %%ymm0, %[q0]\n\t"
"vpslld $16, %%ymm5, %%ymm5\n\t"
"vpaddd %%ymm5, %%ymm1, %[q1]\n\t"
"vpslld $16, %%ymm6, %%ymm6\n\t"
"vpaddd %%ymm6, %%ymm2, %[q2]\n\t"
"vpslld $16, %%ymm7, %%ymm7\n\t"
"vpaddd %%ymm7, %%ymm3, %[q3]\n\t"
: [ap] "+r" (ap), [bp] "+r" (bp), [cnt] "+r" (npair),
[q0] "=x" (q0), [q1] "=x" (q1), [q2] "=x" (q2), [q3] "=x" (q3)
:
: "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm15", "memory"); /* ymm15 kept DECLARED on purpose -- see notes */
{ int32_t *cp = c;
if (first) {
_mm256_store_si256((__m256i *)(cp + (size_t)3 * ldc), q3);
_mm256_store_si256((__m256i *)(cp + (size_t)2 * ldc), q2);
_mm256_store_si256((__m256i *)(cp + (size_t)1 * ldc), q1);
_mm256_store_si256((__m256i *)(cp + (size_t)0 * ldc), q0);
} else {
int32_t *cpr3 = cp + (size_t)3 * ldc;
_mm256_store_si256((__m256i *)cpr3, _mm256_add_epi32(_mm256_load_si256((const __m256i *)cpr3), q3));
int32_t *cpr2 = cp + (size_t)2 * ldc;
_mm256_store_si256((__m256i *)cpr2, _mm256_add_epi32(_mm256_load_si256((const __m256i *)cpr2), q2));
int32_t *cpr1 = cp + (size_t)1 * ldc;
_mm256_store_si256((__m256i *)cpr1, _mm256_add_epi32(_mm256_load_si256((const __m256i *)cpr1), q1));
int32_t *cpr0 = cp + (size_t)0 * ldc;
_mm256_store_si256((__m256i *)cpr0, _mm256_add_epi32(_mm256_load_si256((const __m256i *)cpr0), q0));
} }
}
/* MIKRO-END */
/* ---- ld-aware packing + tiled macro-kernel (base case) ---- */
#pragma GCC push_options
#pragma GCC optimize("O2")
AVX2 static inline void packA2(int ic, int kk, int n, int lda, const T * __restrict A, int sg, const T * __restrict A2) {
const __m256i m16 = _mm256_set1_epi32(0xFFFF);
__m256i half = _mm256_set1_epi32(0x8000);
__asm__ volatile("" : "+x"(half));
/* 常量索引 -> vpermq 立即数 0x88 */
__m256i SHLO = _mm256_setr_epi8(0,1,4,5,8,9,12,13,0,1,4,5,8,9,12,13,0,1,4,5,8,9,12,13,0,1,4,5,8,9,12,13);
__m256i SHHI = _mm256_setr_epi8(2,3,6,7,10,11,14,15,2,3,6,7,10,11,14,15,2,3,6,7,10,11,14,15,2,3,6,7,10,11,14,15);
__asm__ volatile("" : "+x"(SHLO));
__asm__ volatile("" : "+x"(SHHI));
(void)n;
/* UNSWITCHED: the (A2!=0) and (sg>0) decisions are hoisted to the top so each
inner loop is branch-free and no source pointer has to live in an array.
Same stores, same order of arithmetic -> bit-identical panels. */
const size_t st = (size_t)lda;
const T *s0 = A + (size_t)ic * st + kk, *s1 = s0 + st, *s2 = s1 + st, *s3 = s2 + st;
#define PA_EMIT(RO, XV) \
do { __m256i rl = _mm256_permute4x64_epi64(_mm256_shuffle_epi8((XV), SHLO), 0x88); \
__m256i rh = _mm256_permute4x64_epi64( \
_mm256_shuffle_epi8(_mm256_add_epi32((XV), half), SHHI), 0x88); \
T *d = Apk + (size_t)(RO) * APSTR + 32 * u; \
ST(d + 0, rl); _mm_store_si128((__m128i *)(d + 8), _mm256_castsi256_si128(rl)); \
ST(d + 16, rh); _mm_store_si128((__m128i *)(d + 24), _mm256_castsi256_si128(rh)); } while (0)
if (A2) {
const T *t0 = A2 + (size_t)ic * st + kk, *t1 = t0 + st, *t2 = t1 + st, *t3 = t2 + st;
if (sg > 0) {
for (int u = 0; u < KC / 8; u++) {
PA_EMIT(0, _mm256_add_epi32(LD(s0 + 8 * u), LD(t0 + 8 * u)));
PA_EMIT(1, _mm256_add_epi32(LD(s1 + 8 * u), LD(t1 + 8 * u)));
PA_EMIT(2, _mm256_add_epi32(LD(s2 + 8 * u), LD(t2 + 8 * u)));
PA_EMIT(3, _mm256_add_epi32(LD(s3 + 8 * u), LD(t3 + 8 * u)));
}
} else {
for (int u = 0; u < KC / 8; u++) {
PA_EMIT(0, _mm256_sub_epi32(LD(s0 + 8 * u), LD(t0 + 8 * u)));
PA_EMIT(1, _mm256_sub_epi32(LD(s1 + 8 * u), LD(t1 + 8 * u)));
PA_EMIT(2, _mm256_sub_epi32(LD(s2 + 8 * u), LD(t2 + 8 * u)));
PA_EMIT(3, _mm256_sub_epi32(LD(s3 + 8 * u), LD(t3 + 8 * u)));
}
}
} else {
for (int u = 0; u < KC / 8; u++) {
PA_EMIT(0, LD(s0 + 8 * u)); PA_EMIT(1, LD(s1 + 8 * u));
PA_EMIT(2, LD(s2 + 8 * u)); PA_EMIT(3, LD(s3 + 8 * u));
}
}
#undef PA_EMIT
}
#pragma GCC pop_options
#pragma GCC push_options
#pragma GCC optimize("O3")
AVX2 static inline void packB2(int jc, int kk, int n, int ldb, const T * __restrict B, int sg, const T * __restrict B2) {
const __m256i m16 = _mm256_set1_epi32(0xFFFF);
const __m256i half = _mm256_set1_epi32(0x8000);
(void)n;
for (int u = 0; u < NPAIR / 4; u++) {
const T *s = B + (size_t)(kk + 8 * u) * ldb + jc;
const T *t = B2 ? (B2 + (size_t)(kk + 8 * u) * ldb + jc) : 0;
for (int j = 0; j < NC; j += 8) {
T *d = Bpk + (size_t)(j / 8) * (NPAIR * 16 + 24) + (size_t)u * 64;
__m256i L0, L1, L2, L3, H0, H1, H2, H3;
/* [mi4av_] bit-exact, verified on a micro-test (LO/HI both match byte-for-byte):
the two byte-shuffle tables only assemble the low-16 of each dword, i.e.
L_P = (x0[i]&0xffff) | (x1[i]&0xffff)<<16 = vpblendw(x0, vpslld(x1,16), 0xAA);
H_P = high16(x+0x8000) on both rows = vpblendw(vpsrld(x0+half,16), x1+half, 0xAA).
4 vpshufb + 2 vpor -- four of them port-5 uops -- per pair become 0 port-5 uops
and 2 fewer uops per pair: -8 uops and -16 port-5 uops per 32 B output block.
The 8 stores and the 24 vpblendd are untouched. */
#define F11_PAIR(P, LO, HI) \
{ const T *sp = s + (size_t)(2 * P) * ldb + j; \
__m256i x0 = LD(sp), x1 = LD(sp + ldb); \
if (t) { const T *tp = t + (size_t)(2 * P) * ldb + j; \
__m256i y0 = LD(tp), y1 = LD(tp + ldb); \
if (sg > 0) { x0 = _mm256_add_epi32(x0, y0); x1 = _mm256_add_epi32(x1, y1); } \
else { x0 = _mm256_sub_epi32(x0, y0); x1 = _mm256_sub_epi32(x1, y1); } } \
LO = _mm256_blend_epi16(x0, _mm256_slli_epi32(x1, 16), 0xAA); \
HI = _mm256_blend_epi16(_mm256_srli_epi32(_mm256_add_epi32(x0, half), 16), \
_mm256_add_epi32(x1, half), 0xAA); }
F11_PAIR(0, L0, H0)
F11_PAIR(1, L1, H1)
F11_PAIR(2, L2, H2)
F11_PAIR(3, L3, H3)
#undef F11_PAIR
{
__m256i a=_mm256_blend_epi32(L0,L2,0xcc),b=_mm256_blend_epi32(L0,L2,0x33);
__m256i c=_mm256_blend_epi32(L1,L3,0xcc),e=_mm256_blend_epi32(L1,L3,0x33);
ST(d+0,_mm256_blend_epi32(a,c,0xaa));
ST(d+8,_mm256_blend_epi32(c,b,0xaa));
ST(d+16,_mm256_blend_epi32(b,e,0xaa));
ST(d+24,_mm256_blend_epi32(e,a,0xaa));
}
{
__m256i a=_mm256_blend_epi32(H0,H2,0xcc),b=_mm256_blend_epi32(H0,H2,0x33);
__m256i c=_mm256_blend_epi32(H1,H3,0xcc),e=_mm256_blend_epi32(H1,H3,0x33);
ST(d+32,_mm256_blend_epi32(a,c,0xaa));
ST(d+40,_mm256_blend_epi32(c,b,0xaa));
ST(d+48,_mm256_blend_epi32(b,e,0xaa));
ST(d+56,_mm256_blend_epi32(e,a,0xaa));
}
}
}
}
#pragma GCC pop_options
AVX2 static inline __attribute__((always_inline)) void block_mikro(int ic, int jc, int n, int ldc, T *C, int first) {
T *cp0 = C + (size_t)ic * ldc + jc;
for (int r = 0; r < MC; r += MR) {
const int32_t *ap = Apk + (size_t)r * APSTR;
T *cp = cp0 + (size_t)r * ldc;
const int32_t *bp = Bpk;
for (int jg = 0; jg < NC; jg += NR) {
mikro(NPAIR, ap, bp, cp + jg, ldc, first);
bp += (NPAIR * 16 + 24);
}
}
}
/* LEAF SPECIALISED: with BASE==KC==NC==128 every tiled2 leaf call has h==128 and
ldc==h==128, so both become compile-time constants -> the jc/kk/ic loops fully fold. */
AVX2 static void tiled2_128(const T *A1, const T *A2, int sgA, int lda,
const T *B1, const T *B2, int sgB, int ldb, T *C) {
const int n = 128;
const int ldc = 128;
for (int jc = 0; jc < n; jc += NC) {
for (int kk = 0; kk < n; kk += KC) {
packB2(jc, kk, n, ldb, B1, sgB, B2);
for (int ic = n - MC; ic >= 0; ic -= MC) {
packA2(ic, kk, n, lda, A1, sgA, A2);
if (ic - MC >= 0) {
const T *n1 = A1 + (size_t)(ic - MC) * lda + kk;
const T *n2 = A2 ? (A2 + (size_t)(ic - MC) * lda + kk) : 0;
for (int r = 0; r < MC; r++) {
const T *p1 = n1 + (size_t)r * lda;
const T *p2 = n2 ? (n2 + (size_t)r * lda) : 0;
__builtin_prefetch(p1, 0, 2);
if (p2) __builtin_prefetch(p2, 0, 2);
}
}
block_mikro(ic, jc, n, ldc, C, kk == 0);
}
}
}
}
/* correct for any n, just slow */
AVX2 static void generic(int n, const T *A, int lda, const T *B, int ldb, T *C, int ldc) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++) {
uint32_t s = 0;
for (int k = 0; k < n; k++)
s += (uint32_t)A[(size_t)i * lda + k] * (uint32_t)B[(size_t)k * ldb + j];
C[(size_t)i * ldc + j] = (T)s;
}
}
/* tiled base case: requires n % NC == 0, n % KC == 0, n >= MC */
AVX2 static void tiled(int n, const T *A, int lda, const T *B, int ldb, T *C, int ldc) {
/* C is fully written by the kk==0 pass (micro stores instead of RMWs) */
for (int jc = 0; jc < n; jc += NC) {
for (int kk = 0; kk < n; kk += KC) {
packB2(jc, kk, n, ldb, B, 1, (const T *)0);
for (int ic = 0; ic < n; ic += MC) {
packA2(ic, kk, n, lda, A, 1, (const T *)0);
block_mikro(ic, jc, n, ldc, C, kk == 0);
}
}
}
}
AVX2 static int ok_tiled(int n) {
return (n % NC) == 0 && (n % KC) == 0 && (n % MC) == 0 && (MC % MR) == 0 && (NC % NR) == 0;
}
/* ---- Strassen over Z/2^32. Exact: all ops are ring ops of Z/2^32. ---- */
#define STR_DEPTH 6
/* P = X + s*Y in ONE pass over h x h (replaces copyblk + axpy: one write instead of two) */
#pragma GCC push_options
#pragma GCC optimize("O3")
AVX2 static void addblk(int h, T * __restrict P, const T * __restrict X, int ldx, const T * __restrict Y, int ldy, int s, int zp, int sp) {
if(zp && sp){
size_t z=(size_t)h*h;
if(h>=1024){
if(s>0)for(size_t j=0;j<z;j+=8)_mm256_stream_si256((__m256i*)(P+j),_mm256_add_epi32(LD(X+j),LD(Y+j)));
else for(size_t j=0;j<z;j+=8)_mm256_stream_si256((__m256i*)(P+j),_mm256_sub_epi32(LD(X+j),LD(Y+j)));
}else{
if(s>0)for(size_t j=0;j<z;j+=8)ST(P+j,_mm256_add_epi32(LD(X+j),LD(Y+j)));
else for(size_t j=0;j<z;j+=8)ST(P+j,_mm256_sub_epi32(LD(X+j),LD(Y+j)));
}
return;
}
if(zp && h>=256){
for(int rb=0;rb<h;rb+=128)for(int cb=0;cb<h;cb+=128){
T*db=P+zoff(h,rb,cb);
const T*xb=sp?X+zoff(h,rb,cb):X+(size_t)rb*ldx+cb;
const T*yb=sp?Y+zoff(h,rb,cb):Y+(size_t)rb*ldy+cb;
const int sx=sp?128:ldx,sy=sp?128:ldy;
for(int r=0;r<128;r++){
T*d=db+(size_t)r*128;const T*x=xb+(size_t)r*sx,*y=yb+(size_t)r*sy;
__builtin_prefetch(x+sx,0,3);__builtin_prefetch(y+sy,0,3);
if(h>=1024){
if(s>0)for(int j=0;j<128;j+=8)_mm256_stream_si256((__m256i*)(d+j),_mm256_add_epi32(LD(x+j),LD(y+j)));
else for(int j=0;j<128;j+=8)_mm256_stream_si256((__m256i*)(d+j),_mm256_sub_epi32(LD(x+j),LD(y+j)));
}else{
if(s>0)for(int j=0;j<128;j+=8)ST(d+j,_mm256_add_epi32(LD(x+j),LD(y+j)));
else for(int j=0;j<128;j+=8)ST(d+j,_mm256_sub_epi32(LD(x+j),LD(y+j)));
}
}
}
return;
}
for (int i = 0; i < h; i++) {
const T *xp = X + (size_t)i * ldx, *yp = Y + (size_t)i * ldy;
__builtin_prefetch(X + (size_t)(i+1)*ldx, 0, 3); __builtin_prefetch(Y + (size_t)(i+1)*ldy, 0, 3);
if (!zp) {
T *pp = P + (size_t)i * h;
if (h >= 1024) {
if (s > 0) for (int j = 0; j < h; j += 8) _mm256_stream_si256((__m256i *)(pp + j), _mm256_add_epi32(LDA(xp + j), LDA(yp + j)));
else for (int j = 0; j < h; j += 8) _mm256_stream_si256((__m256i *)(pp + j), _mm256_sub_epi32(LDA(xp + j), LDA(yp + j)));
} else {
if (s > 0) for (int j = 0; j < h; j += 8) STA(pp + j, _mm256_add_epi32(LDA(xp + j), LDA(yp + j)));
else for (int j = 0; j < h; j += 8) STA(pp + j, _mm256_sub_epi32(LDA(xp + j), LDA(yp + j)));
}
} else if (h == 256) {
T *p0 = P + (size_t)(i >> 7) * 32768 + (size_t)(i & 127) * 128;
T *p1 = p0 + 16384;
const T *x0 = sp ? X + zoff(256, i, 0) : xp, *x1 = sp ? X + zoff(256, i, 128) : xp + 128;
const T *y0 = sp ? Y + zoff(256, i, 0) : yp, *y1 = sp ? Y + zoff(256, i, 128) : yp + 128;
if (s > 0) {
for (int j = 0; j < 128; j += 8) STA(p0 + j, _mm256_add_epi32(LDA(x0 + j), LDA(y0 + j)));
for (int j = 0; j < 128; j += 8) STA(p1 + j, _mm256_add_epi32(LDA(x1 + j), LDA(y1 + j)));
} else {
for (int j = 0; j < 128; j += 8) STA(p0 + j, _mm256_sub_epi32(LDA(x0 + j), LDA(y0 + j)));
for (int j = 0; j < 128; j += 8) STA(p1 + j, _mm256_sub_epi32(LDA(x1 + j), LDA(y1 + j)));
}
} else {
for (int c = 0; c < h; c += 128) {
T *pp = P + zoff(h, i, c);
const T *xc = sp ? X + zoff(h, i, c) : xp + c, *yc = sp ? Y + zoff(h, i, c) : yp + c;
if (h >= 1024) {
if (s > 0) for (int j = 0; j < 128; j += 8) _mm256_stream_si256((__m256i*)(pp + j), _mm256_add_epi32(LDA(xc + j), LDA(yc + j)));
else for (int j = 0; j < 128; j += 8) _mm256_stream_si256((__m256i*)(pp + j), _mm256_sub_epi32(LDA(xc + j), LDA(yc + j)));
} else {
if (s > 0) for (int j = 0; j < 128; j += 8) STA(pp + j, _mm256_add_epi32(LDA(xc + j), LDA(yc + j)));
else for (int j = 0; j < 128; j += 8) STA(pp + j, _mm256_sub_epi32(LDA(xc + j), LDA(yc + j)));
}
}
}
}
}
#pragma GCC pop_options
#pragma GCC push_options
#pragma GCC optimize("O3")
template<int SA, int SB>
AVX2 static void addblk_pair(int h, T * __restrict P,
const T * __restrict A, int lda, const T * __restrict A2,
T * __restrict Q,
const T * __restrict B, int ldb, const T * __restrict B2) {
for (int i=0;i<h;i++) {
const T *a=A+(size_t)i*lda,*a2=A2+(size_t)i*lda;
const T *b=B+(size_t)i*ldb,*b2=B2+(size_t)i*ldb;
T *p=P+(size_t)i*h,*q=Q+(size_t)i*h;
__builtin_prefetch(a+lda,0,3); __builtin_prefetch(a2+lda,0,3);
__builtin_prefetch(b+ldb,0,3); __builtin_prefetch(b2+ldb,0,3);
for(int j=0;j<h;j+=8) {
__m256i x=LD(a+j), y=LD(a2+j), z=LD(b+j), w=LD(b2+j);
STA(p+j,SA>0?_mm256_add_epi32(x,y):_mm256_sub_epi32(x,y));
STA(q+j,SB>0?_mm256_add_epi32(z,w):_mm256_sub_epi32(z,w));
}
}
}
#pragma GCC pop_options
/* dst = s1*m1 + s2*m2 , ONE pass (M blocks are contiguous, row stride h) */
/* dst = s1*m1 + s2*m2 + s3*m3 + s4*m4 , ONE pass */
#define B11 (A)
#define B12 (ap ? (A + h2) : (A + h))
#define B21 (ap ? (A + 2*h2) : (A + (size_t)h * lda))
#define B22 (ap ? (A + 3*h2) : (A + (size_t)h * lda + h))
#define D11 (B)
#define D12 (bp ? (B + h2) : (B + h))
#define D21 (bp ? (B + 2*h2) : (B + (size_t)h * ldb))
#define D22 (bp ? (B + 3*h2) : (B + (size_t)h * ldb + h))
/* ---- FUSED combine: one pass instead of four (l_sub1pct) --------------------
The shipped rec() makes FOUR passes over the seven M blocks (12 block-reads
for 4 outputs: M1..M5 are each read twice). Holding the seven row vectors in
registers lets all four quadrants be formed from 7 loads, so the combine's
issue cost per 8 outputs goes 24 -> 19 uops and its read volume 12h^2 -> 7h^2.
Same stores, same NT form, byte-exact. */
#pragma GCC push_options
#pragma GCC optimize("O3")
AVX2 static void comb_all(int h, T * __restrict C, int ldc,
const T * __restrict M1, const T * __restrict M2, const T * __restrict M3, const T * __restrict M4,
const T * __restrict M5, const T * __restrict M6, const T * __restrict M7) {
for (int i = 0; i < h; i++) {
const T *a = M1 + (size_t)i * h, *b = M2 + (size_t)i * h, *c = M3 + (size_t)i * h,
*d = M4 + (size_t)i * h, *e = M5 + (size_t)i * h, *f = M6 + (size_t)i * h,
*g = M7 + (size_t)i * h;
T *d1 = C + (size_t)i * ldc, *d2 = d1 + h,
*d3 = d1 + (size_t)h * ldc, *d4 = d3 + h;
int j = 0;
for (; j + 16 <= h; j += 16) { /* [i2y_] 同上 */
{ const int jj = j;
__m256i m1=LDA(a+jj),m2=LDA(b+jj),m3=LDA(c+jj),m4=LDA(d+jj),
m5=LDA(e+jj),m6=LDA(f+jj),m7=LDA(g+jj);
__m256i r1=LDA(a+jj+8),r2=LDA(b+jj+8),r3=LDA(c+jj+8),r4=LDA(d+jj+8),
r5=LDA(e+jj+8),r6=LDA(f+jj+8),r7=LDA(g+jj+8);
_mm256_stream_si256((__m256i *)(d1+jj), _mm256_add_epi32(_mm256_sub_epi32(_mm256_add_epi32(m1,m4),m5),m7));
_mm256_stream_si256((__m256i *)(d1+jj+8), _mm256_add_epi32(_mm256_sub_epi32(_mm256_add_epi32(r1,r4),r5),r7));
_mm256_stream_si256((__m256i *)(d3+jj), _mm256_add_epi32(m2,m4));
_mm256_stream_si256((__m256i *)(d3+jj+8), _mm256_add_epi32(r2,r4));
_mm256_stream_si256((__m256i *)(d2+jj), _mm256_add_epi32(m3,m5));
_mm256_stream_si256((__m256i *)(d2+jj+8), _mm256_add_epi32(r3,r5));
_mm256_stream_si256((__m256i *)(d4+jj), _mm256_add_epi32(_mm256_sub_epi32(_mm256_add_epi32(m1,m3),m2),m6));
_mm256_stream_si256((__m256i *)(d4+jj+8), _mm256_add_epi32(_mm256_sub_epi32(_mm256_add_epi32(r1,r3),r2),r6));
}
}
for (; j + 8 <= h; j += 8) {
__m256i m1 = LDA(a + j), m2 = LDA(b + j), m3 = LDA(c + j), m4 = LDA(d + j),
m5 = LDA(e + j), m6 = LDA(f + j), m7 = LDA(g + j);
_mm256_stream_si256((__m256i *)(d1 + j),
_mm256_add_epi32(_mm256_sub_epi32(_mm256_add_epi32(m1, m4), m5), m7));
_mm256_stream_si256((__m256i *)(d2 + j), _mm256_add_epi32(m3, m5));
_mm256_stream_si256((__m256i *)(d3 + j), _mm256_add_epi32(m2, m4));
_mm256_stream_si256((__m256i *)(d4 + j),
_mm256_add_epi32(_mm256_sub_epi32(_mm256_add_epi32(m1, m3), m2), m6));
}
/* scalar tail removed: same invariant as above. */
}
}
#pragma GCC pop_options
AVX2 static void rec(int n, const T *A, int lda, const T *B, int ldb, T *C, int ldc,
T *scr, int depth, int bp, int ap) {
if (depth >= STR_DEPTH || (n & 1) || n <= BASE || !ok_tiled(n)) {
if (ok_tiled(n)) tiled(n, A, lda, B, ldb, C, ldc);
else generic(n, A, lda, B, ldb, C, ldc);
return;
}
const int h = n / 2;
const size_t h2 = (size_t)h * h;
T *S = scr; /* 7 result blocks M1..M7 then 2 scratch S blocks */
T *M1 = S, *M2 = M1 + h2 + 4608, *M3 = M2 + h2 + 4608, *M4 = M3 + h2 + 4608,
*M5 = M4 + h2 + 4608, *M6 = M5 + h2 + 4608, *M7 = M6 + h2 + 4608;
T *P = M7 + h2 + 4608; /* operand scratch block 1 (h x h, ldp = h) */
T *Q = P + h2 + 4608; /* operand scratch block 2 */
T *sub = Q + h2 + 4608; /* recursion arena */
/* Each of the 7 products uses an operand that is A1 (+/- A2) on the A side and
B1 (+/- B2) on the B side. When the children are LEAVES (h <= BASE) the summed
operand is consumed only by the packers, so we fuse the sum INTO the packer and
never materialise P/Q: that removes 2 of every 4 accesses per summed operand
element (addblk's write + the packer's read of it, replaced by a second load of
the original block, which is exactly what addblk did anyway). */
#define LOP(a1, a2, sgA, b1, b2, sgB, Mi) \
do { \
if (h <= BASE) { \
tiled2_128((a1), (a2), (sgA), (ap ? 128 : lda), \
(b1), (b2), (sgB), (bp ? 128 : ldb), (Mi)); \
} else { \
const T *pa = (a1); int la = lda; \
const T *pb = (b1); int lb = ldb; \
if ((a2) && (b2)) { \
addblk_pair<(sgA),(sgB)>(h,P,(a1),lda,(a2),Q,(b1),ldb,(b2)); \
pa=P; la=h; pb=Q; lb=h; \
} else { \
if (a2) { addblk(h,P,(a1),lda,(a2),lda,(sgA),1,ap); pa=P; la=h; } \
if (b2) { addblk(h,Q,(b1),ldb,(b2),ldb,(sgB),ZQ,bp); pb=Q; lb=h; } \
} \
rec(h, pa, la, pb, lb, (Mi), h, sub, depth + 1, bp, ap); \
} \
} while (0)
LOP(B21, B11, -1, D11, D12, +1, M6); /* M6 = (A21-A11)(B11+B12) */
LOP(B21, B22, +1, D11, 0, +1, M2); /* M2 = (A21+A22) B11 */
LOP(B22, 0, +1, D21, D11, -1, M4); /* M4 = A22 (B21-B11) */
LOP(B11, B22, +1, D11, D22, +1, M1); /* M1 = (A11+A22)(B11+B22) */
LOP(B11, 0, +1, D12, D22, -1, M3); /* M3 = A11 (B12-B22) */
LOP(B11, B12, +1, D22, 0, +1, M5); /* M5 = (A11+A12) B22 */
LOP(B12, B22, -1, D21, D22, +1, M7); /* M7 = (A12-A22)(B21+B22) */
#undef LOP
/* C11 = M1 + M4 - M5 + M7 ; C12 = M3 + M5 ; C21 = M2 + M4 ; C22 = M1 - M2 + M3 + M6 */
comb_all(h, C, ldc, M1, M2, M3, M4, M5, M6, M7);
}
#undef B11
#undef B12
#undef B21
#undef B22
#undef D11
#undef D12
#undef D21
#undef D22
/* Update an already materialized S or T block without a separate copy.
[7] verbatim. */
#pragma GCC push_options
#pragma GCC optimize("O3")
AVX2 static void mutate_blk(int h, T *dst, const T *src, int lds, int reverse, int zp, int sp) {
if(zp && sp){
size_t z=(size_t)h*h;
if(reverse)for(size_t j=0;j<z;j+=8)ST(dst+j,_mm256_sub_epi32(LD(src+j),LD(dst+j)));
else for(size_t j=0;j<z;j+=8)ST(dst+j,_mm256_sub_epi32(LD(dst+j),LD(src+j)));
return;
}
if(zp && h>=256){
for(int rb=0;rb<h;rb+=128)for(int cb=0;cb<h;cb+=128){
T*db=dst+zoff(h,rb,cb);
const T*sb=sp?src+zoff(h,rb,cb):src+(size_t)rb*lds+cb;
int ss=sp?128:lds;
for(int r=0;r<128;r++){
T*d=db+(size_t)r*128;const T*s=sb+(size_t)r*ss;__builtin_prefetch(s+ss,0,3);
if(reverse)for(int j=0;j<128;j+=8)ST(d+j,_mm256_sub_epi32(LD(s+j),LD(d+j)));
else for(int j=0;j<128;j+=8)ST(d+j,_mm256_sub_epi32(LD(d+j),LD(s+j)));
}
}
return;
}
for (int i=0;i<h;i++) {
const T *s = src + (size_t)i*lds;
__builtin_prefetch(s + lds, 0, 3);
if (!zp) {
T *d = dst + (size_t)i*h;
if (reverse) for(int j=0;j<h;j+=8) STA(d+j,_mm256_sub_epi32(LDA(s+j),LDA(d+j)));
else for(int j=0;j<h;j+=8) STA(d+j,_mm256_sub_epi32(LDA(d+j),LDA(s+j)));
} else if (h == 256) {
T *d0 = dst + zoff(256, i, 0), *d1 = d0 + 16384;
const T *s0 = sp ? src + zoff(256, i, 0) : s, *s1 = sp ? src + zoff(256, i, 128) : s + 128;
if (reverse) {
for(int j=0;j<128;j+=8) STA(d0+j,_mm256_sub_epi32(LDA(s0+j),LDA(d0+j)));
for(int j=0;j<128;j+=8) STA(d1+j,_mm256_sub_epi32(LDA(s1+j),LDA(d1+j)));
} else {
for(int j=0;j<128;j+=8) STA(d0+j,_mm256_sub_epi32(LDA(d0+j),LDA(s0+j)));
for(int j=0;j<128;j+=8) STA(d1+j,_mm256_sub_epi32(LDA(d1+j),LDA(s1+j)));
}
} else {
for (int c = 0; c < h; c += 128) {
T *d = dst + zoff(h, i, c);
const T *sc = sp ? src + zoff(h, i, c) : s + c;
if (reverse) for(int j=0;j<128;j+=8) STA(d+j,_mm256_sub_epi32(LDA(sc+j),LDA(d+j)));
else for(int j=0;j<128;j+=8) STA(d+j,_mm256_sub_epi32(LDA(d+j),LDA(sc+j)));
}
}
}
}
AVX2 static void comb_win(int h, T *C, int ldc, const T *M1, const T *M2,
const T *M3, const T *M4, const T *M5,
const T *M6, const T *M7) {
for(int i=0;i<h;i++) {
const T *a=M1+(size_t)i*h,*b=M2+(size_t)i*h,*c=M3+(size_t)i*h,
*d=M4+(size_t)i*h,*e=M5+(size_t)i*h,*f=M6+(size_t)i*h,*g=M7+(size_t)i*h;
T *o11=C+(size_t)i*ldc,*o12=o11+h,*o21=o11+(size_t)h*ldc,*o22=o21+h;
int j=0;
for(;j+16<=h;j+=16) { /* [i2y_] 整条 64 B 线一次发完(每象限两条 32 B 存背靠背) */
{ const int jj=j;
__m256i p1=LDA(a+jj),p2=LDA(b+jj),p3=LDA(c+jj),p4=LDA(d+jj),
p5=LDA(e+jj),p6=LDA(f+jj),p7=LDA(g+jj);
__m256i q1=LDA(a+jj+8),q2=LDA(b+jj+8),q3=LDA(c+jj+8),q4=LDA(d+jj+8),
q5=LDA(e+jj+8),q6=LDA(f+jj+8),q7=LDA(g+jj+8);
__m256i u2=_mm256_add_epi32(p1,p6), u3=_mm256_add_epi32(u2,p7), u4=_mm256_add_epi32(u2,p5);
__m256i v2=_mm256_add_epi32(q1,q6), v3=_mm256_add_epi32(v2,q7), v4=_mm256_add_epi32(v2,q5);
_mm256_stream_si256((__m256i*)(o11+jj),_mm256_add_epi32(p1,p2));
_mm256_stream_si256((__m256i*)(o11+jj+8),_mm256_add_epi32(q1,q2));
_mm256_stream_si256((__m256i*)(o21+jj),_mm256_sub_epi32(u3,p4));
_mm256_stream_si256((__m256i*)(o21+jj+8),_mm256_sub_epi32(v3,q4));
_mm256_stream_si256((__m256i*)(o12+jj),_mm256_add_epi32(u4,p3));
_mm256_stream_si256((__m256i*)(o12+jj+8),_mm256_add_epi32(v4,q3));
_mm256_stream_si256((__m256i*)(o22+jj),_mm256_add_epi32(u3,p5));
_mm256_stream_si256((__m256i*)(o22+jj+8),_mm256_add_epi32(v3,q5));
}
}
for(;j<h;j+=8) {
__m256i p1=LDA(a+j),p2=LDA(b+j),p3=LDA(c+j),p4=LDA(d+j),
p5=LDA(e+j),p6=LDA(f+j),p7=LDA(g+j);
__m256i u2=_mm256_add_epi32(p1,p6);
__m256i u3=_mm256_add_epi32(u2,p7);
__m256i u4=_mm256_add_epi32(u2,p5);
_mm256_stream_si256((__m256i*)(o11+j),_mm256_add_epi32(p1,p2));
_mm256_stream_si256((__m256i*)(o12+j),_mm256_add_epi32(u4,p3));
_mm256_stream_si256((__m256i*)(o21+j),_mm256_sub_epi32(u3,p4));
_mm256_stream_si256((__m256i*)(o22+j),_mm256_add_epi32(u3,p5));
}
}
}
AVX2 static void comb_win_interleaved(int h, T *C, int ldc, const T *M1, const T *M2,
const T *M3, const T *M4, const T *M5,
const T *M6, const T *M7) {
for(int i=0;i<h;i++) {
const T *a=M1+(size_t)i*(7*h),*b=M2+(size_t)i*(7*h),*c=M3+(size_t)i*(7*h),
*d=M4+(size_t)i*(7*h),*e=M5+(size_t)i*(7*h),*f=M6+(size_t)i*(7*h),*g=M7+(size_t)i*(7*h);
T *o11=C+(size_t)i*ldc,*o12=o11+h,*o21=o11+(size_t)h*ldc,*o22=o21+h;
int j=0;
for(;j+16<=h;j+=16) { /* [i2y_] 整条 64 B 线一次发完(每象限两条 32 B 存背靠背) */
{ const int jj=j;
__m256i p1=LDA(a+jj),p2=LDA(b+jj),p3=LDA(c+jj),p4=LDA(d+jj),
p5=LDA(e+jj),p6=LDA(f+jj),p7=LDA(g+jj);
__m256i q1=LDA(a+jj+8),q2=LDA(b+jj+8),q3=LDA(c+jj+8),q4=LDA(d+jj+8),
q5=LDA(e+jj+8),q6=LDA(f+jj+8),q7=LDA(g+jj+8);
__m256i u2=_mm256_add_epi32(p1,p6), u3=_mm256_add_epi32(u2,p7), u4=_mm256_add_epi32(u2,p5);
__m256i v2=_mm256_add_epi32(q1,q6), v3=_mm256_add_epi32(v2,q7), v4=_mm256_add_epi32(v2,q5);
_mm256_stream_si256((__m256i*)(o11+jj),_mm256_add_epi32(p1,p2));
_mm256_stream_si256((__m256i*)(o11+jj+8),_mm256_add_epi32(q1,q2));
_mm256_stream_si256((__m256i*)(o21+jj),_mm256_sub_epi32(u3,p4));
_mm256_stream_si256((__m256i*)(o21+jj+8),_mm256_sub_epi32(v3,q4));
_mm256_stream_si256((__m256i*)(o12+jj),_mm256_add_epi32(u4,p3));
_mm256_stream_si256((__m256i*)(o12+jj+8),_mm256_add_epi32(v4,q3));
_mm256_stream_si256((__m256i*)(o22+jj),_mm256_add_epi32(u3,p5));
_mm256_stream_si256((__m256i*)(o22+jj+8),_mm256_add_epi32(v3,q5));
}
}
for(;j<h;j+=8) {
__m256i p1=LDA(a+j),p2=LDA(b+j),p3=LDA(c+j),p4=LDA(d+j),
p5=LDA(e+j),p6=LDA(f+j),p7=LDA(g+j);
__m256i u2=_mm256_add_epi32(p1,p6);
__m256i u3=_mm256_add_epi32(u2,p7);
__m256i u4=_mm256_add_epi32(u2,p5);
_mm256_stream_si256((__m256i*)(o11+j),_mm256_add_epi32(p1,p2));
_mm256_stream_si256((__m256i*)(o12+j),_mm256_add_epi32(u4,p3));
_mm256_stream_si256((__m256i*)(o21+j),_mm256_sub_epi32(u3,p4));
_mm256_stream_si256((__m256i*)(o22+j),_mm256_add_epi32(u3,p5));
}
}
}
#pragma GCC pop_options
AVX2 static void rec_w(int n, const T *A, int lda, const T *B, int ldb,
T *C, int ldc, T *scr, int depth, int bp, int ap) {
if (n<=256 || depth>=STR_DEPTH || (n&1) || !ok_tiled(n)) {
rec(n,A,lda,B,ldb,C,ldc,scr,depth,bp,ap); return;
}
const int h=n/2; const size_t h2=(size_t)h*h;
T *M1=scr,*M2=M1+h2+4608,*M3=M2+h2+4608,*M4=M3+h2+4608,
*M5=M4+h2+4608,*M6=M5+h2+4608,*M7=M6+h2+4608;
T *P=M7+h2+4608,*Q=P+h2+4608,*sub=Q+h2+4608;
const bool interleaved = (depth == 0 && n == 2048);
if (interleaved) {
M1=scr; M2=M1+h; M3=M2+h; M4=M3+h; M5=M4+h; M6=M5+h; M7=M6+h;
P=scr+7*h2+7*4608; Q=P+h2+4608; sub=Q+h2+4608;
if (g_rel && depth == 0) { /* mi2aq_: relocation is depth-0 only */
P = g_pool; Q = scr + 7*h2; sub = g_pool + h2;
}
} else if (g_rel && depth == 2) {
sub = g_deep;
}
const int mld=interleaved?7*h:h;
const size_t q2=(size_t)h*h;
const T *A11=A,*A12=ap?A+q2:A+h,*A21=ap?A+2*q2:A+(size_t)h*lda,*A22=ap?A+3*q2:A21+h;
const T *B11=B,*B12=bp?B+q2:B+h,*B21=bp?B+2*q2:B+(size_t)h*ldb,*B22=bp?B+3*q2:B21+h;
rec_w(h,A12,lda,B21,ldb,M2,mld,sub,depth+1,bp,ap); // P2
rec_w(h,A11,lda,B11,ldb,M1,mld,sub,depth+1,bp,ap); // P1
addblk(h,Q,B12,ldb,B11,ldb,-1,ZQ,bp); // T1 [mi2au_ ord-1: 第一对对调]
addblk(h,P,A21,lda,A22,lda,+1,1,ap); // S1
rec_w(h,P,h,Q,h,M5,mld,sub,depth+1,1,1); // P5
mutate_blk(h,P,A11,lda,0,1,ap); // S2 = S1-A11
mutate_blk(h,Q,B22,ldb,1,ZQ,bp); // T2 = B22-T1
rec_w(h,P,h,Q,h,M6,mld,sub,depth+1,1,1); // P6
mutate_blk(h,P,A12,lda,1,1,ap); // S4 = A12-S2
mutate_blk(h,Q,B21,ldb,0,ZQ,bp); // T4 = T2-B21
rec_w(h,A22,lda,Q,h,M4,mld,sub,depth+1,1,ap); // P4
rec_w(h,P,h,B22,ldb,M3,mld,sub,depth+1,bp,1); // P3
addblk(h,Q,B22,ldb,B12,ldb,-1,ZQ,bp); // T3
addblk(h,P,A11,lda,A21,lda,-1,1,ap); // S3
rec_w(h,P,h,Q,h,M7,mld,sub,depth+1,1,1); // P7
if(interleaved) comb_win_interleaved(h,C,ldc,M1,M2,M3,M4,M5,M6,M7);
else comb_win(h,C,ldc,M1,M2,M3,M4,M5,M6,M7);
}
AVX2 void matrix_multiply(int n, const T *A, const T *B, T *C) {
unsigned long long al = (unsigned long long)(size_t)A | (unsigned long long)(size_t)B | (unsigned long long)(size_t)C;
if (n <= BASE || !ok_tiled(n) || (al & 31)) {
if (ok_tiled(n) && !(al & 31)) tiled(n, A, n, B, n, C, n);
else generic(n, A, n, B, n, C, n);
return;
}
/* depth-first arena: 9 h^2 blocks at each level along the path */
size_t need = 0, h = (size_t)n;
while (h > (size_t)BASE) { h /= 2; need += 9 * (h * h + 4608); }
const int rel = (n == 2048);
size_t need_alloc = need;
if (rel) { /* mi2ap_: [7h^2][Q][最深一帧] */
const size_t h0 = (size_t)n / 2;
need_alloc = 7*h0*h0 + (h0*h0 + 4608) + 9*((size_t)BASE*BASE + 4608);
}
static T *scr = 0; static size_t cap = 0;
if (need_alloc > cap) { if (scr) free(scr); cap = need_alloc + 1;
void *pv = 0; if (posix_memalign(&pv, (size_t)2 << 20, cap * sizeof(T))) return; scr = (T *)pv; (void)madvise(scr,(cap*sizeof(T))&~size_t(4095),MADV_HUGEPAGE); }
g_rel = rel;
if (rel) {
const size_t h0 = (size_t)n / 2;
g_pool = C;
g_deep = scr + 7*h0*h0 + (h0*h0 + 4608);
}
rec_w(n, A, n, B, n, C, n, scr, 0, 0, 0);
}
| Compilation | N/A | N/A | Compile OK | Score: N/A | 显示更多 |
| Testcase #1 | 239.825 ms | 48 MB + 564 KB | Accepted | Score: 100 | 显示更多 |