Skip to content

feat(w4): 完整 Qwen3 外置权重、多 hart 执行与验证优化 - #104

Merged
jizhenjun merged 58 commits into
ScratchV-Compiler:mainfrom
yuki-328:codex/w4-linux-pr
Oct 22, 2026
Merged

jizhenjun merged 58 commits into
ScratchV-Compiler:mainfrom
yuki-328:codex/w4-linux-pr

Conversation

@yuki-328

@yuki-328 yuki-328 commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

完整 Qwen3 的权重和激活超出小图内嵌常量路径。本 PR 提供外置权重与完整 RV64/QEMU 前向链,并增加可选多 hart 和算子优化;默认运行方式保持单 hart。

范围:FP32、batch=1、L=256、28 层、无 KV cache;Ubuntu 24.04 / Python 3.12,目标 RV64GC/LP64D、QEMU virt 裸机。W3 修复与 W4 优化在同一 PR 交付,已标记为 Ready for review,尚不代表团队验收或真实硬件性能。

基线与改动

软仿优化

围绕 QEMU 软仿的计算并行、数据布局、运行器开销和验证链路进行优化,具体包括:

  • 并行:可选 --harts 1/2/4/auto,最多 4;门铃通知与 WFI 等待;MatMul 和独立 Softmax 行并行、同形状回调复用及写回融合有限性检查,保留计算顺序、错误传播和工作区复用。
  • 显式策略:--matmul-tile 1x4/2x4/1x8;--matmul-rhs-layout column-panel 用于符合条件的常量 RHS/转置链;共享或动态 RHS 保留原布局。两缓冲 two-buffer-pad-4k 仍是 QEMU 实验选项。RVV 负收益候选未纳入正式实现。
  • 运行器:UART 完成事件与 QMP nodelay,保留 stop 后帧复核、转储、quit 和异常清理;高 FD 等待改用 poll(),失效 FD/等待错误明确传播。
  • CI:20 次清理循环仅 schedule/manual;普通 PR 保留一次。收敛同 job 及显式委托的跨工作流重复单测,保留真实 RV64/musl、Qwen 小图、W4 必跑 JUnit 门槛及最终总验收。

默认值不变: 1 hart / sequential / 1x4 / original / padding none。auto 只在启动/构建时按进程可用 CPU 选择 1/2/4,不是动态调度;已构建 ELF 的 hart 数不会静默改变。

对应报告已随本 PR 归档,可直接在 GitHub 阅读:

同配置完整模型前向 1384.65 s → 410.53 s(3.373×),CPU 总时间增加 5.46%,38,895,616 个输出逐位一致;完整指标见下文。这是已有候选的单次配对结果,不是当前 PR HEAD 的完整重测,不能与小图收益连乘。

本地完整诊断 HTML、大 JSON、原始数组和采样仍保存在被 Git 忽略的 output/;公开报告列出相对来源索引,不发布个人机器路径。

AI 审查修复与全部文件复核(2026-10-22)

本轮提交 069d4c86edbafabc4ccef83ebe2bc24fd0545304 修复审查工具,未改变模型代码、默认 hart 或 WSL 配置:

  • 文件 API 与已有 bot 评论均使用分页;核对 changed_files、唯一文件名和 head,避免仅取首 30 个。
  • 每批 10 文件、单批并发,取消全局 10 文件截断。429/5xx/超时有限重试;空或损坏响应、响应截断、无/不完整 patch、缺失/取消批次均显式计入失败或不可审查。
  • 每文件保存结果,失败也上传 JSON/完整 Markdown;有缺口最终检查失败,旧 head 不覆盖新评论。支持失败批次重跑。超过 2560 文件明确拒绝,避免 GitHub 的 256 job 矩阵上限;不宣称已审。
  • 保留 pull_request_target 的可信 base checkout,不执行 PR head 代码。workflow_dispatch 增加 pr_number 输入。
  • 最终直接边界测试 56 passed / 0 skipped;此前 AI + 现有 CI 合同 69 passed(重叠,不累加);119 篇文档、226 个 Bash 块检查通过。真实 GitHub 分页为 30/30/26,86 个原有文件全部取得;规划为 9 批,没有缺失/截断 patch。该检查未调用外部 AI。

本对话此前按 CI/文档、代码生成、运行时、W3、W4、新审查工具六批,对 069d4c8 的 89/89 文件完成差异与上下文审查(原有 86 + 新增 3),没有漏审文件;这与 SenseNova 远端结果分开记录,也不构成团队批准。

此前确认的 P2 已在 b77e45f 修复: Host C 受监督编译器与 worker 共享外层拥有的进程组;外层超时、取消或 worker 退出时统一清理,包含 worker 被暂停及编译器孙进程场景。独立编译仍使用隔离组。内层异常时管道排空有界,保留原始超时/错误和部分日志。新增真实进程回归只用 Python 替身,未执行模型或真实 C 编译;PR 当前已标记为 Ready for review。

另修正 1 项 P3:W4/evolution.md 对已修复绑定优先级的陈旧说明。旧 AI 评论中关于单测丢失、缺失 W4 gate、未固定资产、W3 必需 flags、padding 采样等指摘已用完整上下文核对,未形成这些问题的有效证据,不放宽数值阈值。

远端验证限制: pull_request_target 本次仍执行上游 main 的旧工作流,因此新提交的旧 AI check 即使绿色,也不是新版分页/分批实现的验收。当前账号无上游 dispatch 权限、fork 无该审查密钥;需修复进入可信上游后,由维护者完成新版真实 SenseNova 集成验证。没有把这项限制计成已完成。

验证摘要

以下为分阶段记录,存在重叠,不累加成唯一测试总数:

阶段 结果
优化后的跨模块单测及实际小图 1488 passed / 4 skipped
CI 合同/路由及保留的实际 RV64 173 passed
修正必跑参数化名称后的门槛合同 374 passed
PR 审查:W3 venv、默认/手动/auto、错误与超时 65 passed / 0 skipped
最终高 FD 修复:UART/QMP/退出/清理 31 passed / 0 skipped;含 11 项新增边界用例
Host C 超时/取消/嵌套进程清理(b77e45f) 36 passed / 0 skipped;含 9 项新 Host 进程用例及 5 项新运行器边界用例
#114 主干 CI 整合后 172 workflow/routing checks passed
最终文档 119 篇、226 个 Bash 块检查通过;新增 3 个相对链接有效
本次报告发布(234e114,仅文档) 3 篇 Markdown、1 个 Bash 块语法、9 个本地链接、JSON 数值一致性与路径脱敏通过

4 项跳过为 3 个需单独导出制品的优化检查及 1 个 Linux 不适用的 Windows junction 检查。首次集成 pytest 通过后,旧参数化名称使后置门槛报错;修正门槛后,对同一保留 JUnit 的 13 个必跑节点重新检查,均实际执行且无 skip/failure/error。失败及修正历史保留;这不是另一次模型执行。

本次发布没有重跑完整模型,也没有修改 WSL 配置。

已有完整模型对照(2026-10-22)

固定 full_seed_0,两边均使用 blocked_fma / 2x4 / column-panel / padding none,单/四 hart 各一次;相同模型、输入与数值配置,38,895,616 个 FP32 输出逐位一致。两侧对 ORT 最大绝对误差均 8.58306884765625e-05 < 0.001(rtol=0),数值检查、12 项 FMA 检查和保留数组审计通过。

指标 1 hart 4 hart
前向耗时 1384.65 s 410.53 s
QEMU CPU 总时间 1385.80 s 1461.40 s
平均 CPU 占用(100%=一核) 99.99% 355.62%
观测峰值 RSS 5.3957 GiB 5.3903 GiB

同配置并行加速 3.373×、耗时减少 70.35%,CPU 总时间增加 5.46%。前向从 QEMU 启动计到 UART 完成帧确认;CPU 含整个 QEMU 生命周期。RSS 两边均有少量采样缺失,内存只能称基本持平。

这些完整运行早于最终宿主高 FD 修复,不是最终推送 HEAD 的重新执行或重测。原始报告与数组保留在本地;不以旧异常计时或历史 Actions 记录计算本次倍数。不同形状的小图微内核/面板收益不能与 3.373×直接相乘。单次配对也不代表所有模型、真实 RISC-V 或 NPU。

远端 CI 记录

本次报告发布提交 234e1147e173f5f0721608842fc158dac8558fa9 仅变更 5 个文档文件;3 篇 Markdown、1 个 Bash 块语法、9 个本地链接、JSON 数值一致性及路径脱敏检查通过。下方为此前代码提交的 CI 记录,不作为本次文档 HEAD 的新 CI 结论。本次未手动触发或重跑 CI/AI 审查,未重跑完整模型,未修改 CI 或 WSL 配置。

此前代码提交 b77e45fc2a508dded0e0efd182187cd924fbea9b 的 CI #39734573941 全部通过,包括最终 CI acceptance。本地相关验证 36 passed / 0 skipped;远端 W4 小图及通用检查通过,4 个完整模型相关任务全部按预期跳过。未重跑完整模型,未修改 CI 或 WSL 配置。

新增 Host 清理 9 项和运行器边界 5 项在通用 test 作业逐项实际通过,无跳过。通用 5521 passed / 79 skipped,另 7 项 simulator 通过;W4 显式集合 1528 passed / 4 skipped。新 Host 测试文件由通用作业覆盖。

此前 Host C 修复发布时未主动触发 AI 审查;仓库在该次推送后自动触发旧 AI 工作流,取消请求当时被上游权限限制拒绝(HTTP 403)。这是该次发布的历史记录;本次不追加 AI 审查。新版 AI 真实集成仍待可信上游部署。

边界与待验收事项

  • 4 hart 的剩余波动尚未精确拆分为宿主调度、频率、硬件缓存等因素;auto 不处理 cgroup CPU 带宽配额。
  • column-panel 的 ELF 与物理布局 bundle 必须配套;共享/动态 RHS 保留原布局。padding 默认关闭,不能保证所有形状受益。
  • QEMU virt 门铃地址在真实 RISC-V 平台需要适配;没有真实 RISC-V/NPU 性能或部署验收。
  • 同一候选的 W3 证据复核、E1/E3/E5 独立重建执行、真实 schedule Nightly、接口与团队验收仍分别完成。W5 token 循环/文本生成不属于本 PR 的完成声明。

复现接口:运行合同、Linux 复现、验证与优化选项。

Add bounded external weight bundles, full-model memory layout, Tensor-C lowering, segmented bare-metal QEMU loading and strict retained-array verification. Include Linux QMP shutdown and virtualenv launch fixes, regression coverage, CI entry points and public reproduction contracts.

Linux full_seed_0 evidence: all 38,895,616 logits compared, max_abs 8.58306884765625e-5 < 1e-3. W4 regression selection: 1017 passed, one platform-specific skip. Preserve the actual execution SHAs and pending remote validation and independent team acceptance.
@github-actions

github-actions Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🤖 AI Code Review

共审查 10 个变更文件
⚠️ 另有 18 个文件超过上限(最多 10 个)未审查

📁 .github/workflows/ai-code-review.yml

🔴 **Security: `pull_request_target` misuse risk** — Every future edit to this workflow that checks out the PR head or installs PR-provided dependencies will leak `SENSENOVA_API_KEY` to untrusted code. Consider adding a prominent comment or a pre-merge check (e.g., `grep` guard in a lint step) to prevent regression. The current code is safe (base-branch checkout, `persist-credentials: false`), but the blast radius of a future mistake is large.

🔴 **Unhandled crash in `prepare` finally block** — Line `fs.mkdirSync('review-plan', {recursive: true})` is outside the try. If it throws, the `catch` is skipped and `finally` runs `writeFileSync` into a non-existent directory → unhandled exception → step fails silently. The `plan` step with `if: always()` then runs against a missing/corrupt `raw.json`, producing an invalid matrix → `fromJSON()` error in the `review` job.
Suggestion: Move `mkdirSync` inside the try, or guard `writeFileSync` with `fs.mkdirSync` again.

🟡 **`plan` step may produce invalid matrix** — `if: always()` means `plan` runs even when `raw.json` is error-only (missing `files` array). If `scripts/ai_code_review.py plan` outputs invalid JSON or an empty object, `fromJSON(needs.prepare.outputs.matrix)` will throw. Add a `steps.plan.outputs.matrix` guard or a fallback to an empty matrix.

🟡 **`max-parallel: 1` + `timeout-minutes: 40` is tight** — Large PRs with many batches will silently time out. Consider raising the timeout or adding a pre-check in `prepare` that caps total batch count.

🟡 **Stale-head check is too late** — The head SHA comparison runs only after all review batches complete. If the PR changes during review, you've burned API calls on stale diffs. Consider checking head SHA in the `prepare` job too and fail early if it moved between `pulls.get` calls (already partially done with `data.head` vs `data.head_after`).

🟡 **Per-job permissions could be tighter** — `prepare` only needs `contents: read` + `pull-requests: read`; `review` only needs `contents: read`. Setting job-level `permissions` narrows the blast radius if `pull_request_target` is misconfigured.

🟡 **No early validation of `SENSENOVA_API_KEY`** — Old code checked key presence before looping. Now, a missing key causes every matrix batch to fail individually. A single check in `prepare` or a guard before `review` dispatch would fail fast.

🟡 **`workflow_dispatch` is not branch-restricted** — `pull_request_target` is constrained to `main`, but `workflow_dispatch` runs on any ref. If triggered on a feature branch, the checkout is that branch, not `main`. Add `branches: [main]` to `workflow_dispatch` if only main-branch reviews are intended.

💭 **Stale-head rewrite in `ai-code-review` job** — Mutates `summary.complete` and rewrites both markdown files, but `summary.json` is written first. If the markdown rewrite fails (permissions, disk), you have inconsistent state. Minor, but wrap in try/catch or reorder.

📁 .github/workflows/ci.yml

Code Review: .github/workflows/ci.yml

🔴 Acceptance job may break when w4 is skipped — Line 620: w4 is added to acceptance.needs, but w4 is conditionally skipped (only runs on PRs with w4 == 'true'). When skipped, needs.w4.result is skipped, not success. If the acceptance logic checks individual job results (not just always()), this will cause false failures on non-PR events or when w4 scope is false. Verify the acceptance step handles skipped results gracefully.

🔴 Silent test coverage loss if referenced workflows don't run — The diff removes ~8 inline pytest steps (PassManager, IR interpreter, LICM, DSL frontend, beautifier, const-merge, PR #37, peephole, regalloc) but we cannot verify w4-full-numeric.yml and llm-deploy.yml contain equivalent coverage. If the referenced workflows lack any of these tests, they silently stop running. Add a comment or assertion confirming coverage parity, or at minimum verify before merging.

🟡 llm job with: block lacks corresponding input in llm-deploy.yml — Line 45: ci_covers_generic_regressions: true is passed to llm-deploy.yml. If that workflow doesn't declare this input (via workflow_call.inputs), GitHub will error on the call. Verify the input is defined, or this will break the llm job at runtime.

🟡 w4 job runs on ubuntu-24.04 by default but is called without runs-on — Line 600–605: The w4 job uses uses: (reusable workflow) but doesn't specify runs-on. If w4-full-numeric.yml doesn't set its own runs-on, it'll run on the default runner. Given QEMU checks, confirm the target runner matches the original job's intent.

💭 ci_covers_generic_regressions comment is misleading — Line 43–44: The comment says "The parallel test job owns generic coverage" but the parameter is passed to the llm deploy workflow, not the test job. The comment should clarify what this flag controls in the consumer workflow.


📁 .github/workflows/llm-deploy.yml

🔴 Bug: github.event_name is workflow_call inside this reusable workflow, so the PR-dedup logic is dead code — Tensor compiler and runtime regressions step (if: github.event_name != 'pull_request' || !inputs.ci_covers_generic_regressions).

When a caller invokes this via uses:, the event name is always workflow_call, never pull_request. So github.event_name != 'pull_request' is permanently true → the full pytest set always runs and the dedup never fires. Symmetrically, Delegated PR RV64 musl execution regression (if: github.event_name == 'pull_request' && …) can never execute.

Suggestion: key off the input alone, since inputs.ci_covers_generic_regressions already defaults to false for schedule/manual/independent callers:

if: ${{ !inputs.ci_covers_generic_regressions }}   # generic set
if: ${{ inputs.ci_covers_generic_regressions }}     # delegated musl case

Same applies to Repeated Linux timeout cleanup regression: it uses github.event_name == 'schedule' || 'workflow_dispatch', which silently skips it for workflow_call callers — verify that's intended, or gate on !inputs.ci_covers_generic_regressions too.

🔴 Bug: W4 summary inverts on success — Require explicitly requested W4 execution reads os.environ["GITHUB_EVENT_NAME"] == "workflow_dispatch", which is workflow_call here. So when W4 is actually requested and passes: requested=False, passed=False, not_run=False (result is success, not skipped) → label FAIL → raise SystemExit → the job exits 1 and fails the run. A green W4 forward is reported as a failure.

Suggestion: derive "requested" from the input only:

requested = os.environ.get("W4_REQUESTED", "").casefold() == "true"

The needs.w4-validation.result already distinguishes skipped/success/failure, so the event-name check adds nothing.

🟡 Coverage silently dropped when delegation is enabled — test_llm_inputs.py, test_w2_runtime_gate.py, test_w2_runtime_metadata.py, test_w2_runtime_reporting.py are removed from the generic list entirely, and the delegated step replaces ~20 files with one test id. The comment asserts CI.test covers them, but nothing in this workflow enforces it. Once the event_name bug above is fixed, every PR gated with ci_covers_generic_regressions: true loses those four files unless CI.test truly includes them. Please confirm CI.test's selection list covers them, and add a failing-mode check (e.g. --collect-only assert on required node ids) so a future CI.test refactor doesn't quietly delete coverage.

🟡 w4-execution-summary runs for schedule too and reports on an unrelated job set — if: always() + needs: [w4-validation] means every nightly writes a "NOT RUN" W4 section, which is probably fine, but a cancelled w4-validation (runner lost, push cancelled) yields result == 'cancelled' → FAIL → summary exits 1 and fails the nightly run. Consider treating cancelled as NOT RUN/neutral, or needs only when requested.

💭 case: ${{ inputs.w4_case || 'full_seed_0' }} — w4_case already has default: full_seed_0, so the || fallback is redundant (and workflow_call inputs can't be unset, only defaulted). Drop it for clarity.

💭 In the delegated step, if tests.xml is missing (collection error before junit emission), ET.parse raises a bare ParseError with no hint. A one-line if not os.path.exists(...) or len(cases) == 0: raise SystemExit("junit xml missing/empty") would make the failure reason obvious.


📁 .github/workflows/w4-nightly.yml

🟡 Case-sensitivity mismatch — YAML if on line 29 uses case-sensitive == 'true', but Python on line 55 uses .casefold(). If W4_NIGHTLY_ENABLED is set to True or TRUE, the job is skipped (YAML), but Python sees it as enabled → results in FAIL instead of DISABLED. Align both: use .casefold()-equivalent in YAML or drop .casefold() in Python.

🟡 Dead exclusion clause — Line 29: github.event_name != 'pull_request' guards against an event that has no trigger in this workflow. Harmless but misleading; remove it or add a comment explaining it's defensive for reuse.

🟡 Concurrent cases share resources? — The concurrency group (line 21) includes inputs.case, so different cases on the same ref run in parallel. If the underlying full-numeric workflow consumes shared resources (GPU, registry quota), this could cause collisions. Confirm parallelism is intentional.

💭 Hardcoded false fields — seven_case_coverage, team_accepted, independent_reproduction are always false. They're informative but could mislead consumers into thinking the workflow attempted them. Consider omitting when they'll never be true, or documenting this contract in the workflow description.

💭 timeout-minutes: 5 on status job — Good. Worth noting it's generous; the Python step should complete in seconds.


📁 docs/llm-deploy-v1.0/Linux实跑报告-2026-10-09.md

Code Review: docs/llm-deploy-v1.0/Linux实跑报告-2026-10-09.md

这是文档文件,无代码正确性/安全漏洞问题。仅标注文档一致性问题:


🟡 文件名与 H1 标题不一致 — 文件路径为 Linux实跑报告-2026-10-09.md,但正文 H1 为"Linux 验收记录:W4 完整前向与 W3 回归(2026-10-09)"。读者通过目录导航会找不到对应关系。
建议:统一命名,或在文件名中体现"验收记录"。

🟡 复现命令运行于 cf0f7d3 而非 W4 原始提交 01aff1d — 复现段声明使用 cf0f7d3(W3 启动器修复提交),但正文强调 W4 运行身份为 01aff1d。虽然正文已声明"W4 原始运行身份仍按上表保存",但复现命令实际跑的是两个不同提交的混合态。如果目标是复现 W4 的 3448s 耗时和数值结果,运行者可能得到与表格不同的微差异。
建议:在复现段开头明确标注"以下命令复现 W4 + W3 修复后的端到端流程,非 01aff1d 单点重现",并给出 W4 单独复现的 diff 步骤。

💭 信息密度偏高 — 部分段落(如"Linux 必跑检查覆盖…")单段包含 5+ 个独立检查点。可考虑拆为 bullet list 提升可扫描性,尤其是当读者需要定位某项检查是否覆盖时。

💭 证据目录结构可用 tree 图示替代嵌套文本 — "证据与验收边界"段用文字描述 output/w4-linux-20261009/ 下十余个子目录及其用途。一个简化 tree 输出会比连续文字更易验证目录关系完整性。


整体评价:文档完整度高——源码身份、环境版本、阈值、误差、审计边界、负面清单(未启用 Nightly、W5/W6 另行验收)均有明确交代,复现命令含 set -euo pipefail 和固定线程数,实践良好。


📁 docs/llm-deploy-v1.0/W1/interfaces.md

🟡 Table/§5.4 wording tension — "小模型 ABI 保持兼容" in the table can be misread as "interchangeable with W4 ABI", directly contradicting §5.4's explicit "不能把 W4 的 workspace/weights 参数按旧签名传递" and "不能套用旧固定地址". Suggest "小模型 ABI 不受影响" to match the intent (independent, not interchangeable).

🟡 §5.4 paragraph density — Five distinct concerns (scope boundary, W4 API shape, cross-refs, incompatibility warning, out-of-scope items) packed into one paragraph. Consider a bullet list to match the scannability of §5.2 and the rest of the doc.

💭 Verify cross-reference paths — ../W4/runtime-contract.md and ../W4/validation.md — confirm these resolve to actual files in the repo tree; broken links in a design doc erode trust in the boundary claims they support.


📁 docs/llm-deploy-v1.0/W3/Linux-CI与Nightly.md

🔴 python 在 Ubuntu 24.04 上可能不存在 — 全文多处由 "$SCRATCHV_PYTHON" 改为裸 python。Ubuntu 24.04 默认只装 /usr/bin/python3,/usr/bin/python 需额外安装 python-is-python3。按指南在干净环境复现会直接 command not found,且这是"对外复现"页面,影响面是全部外部用户。
建议:改用 python3(或明确 python3.12),或在 LINUX_REPRODUCTION.md 前置条件中显式声明该依赖并加一条 command -v python 校验。

🟡 解释器身份未被固定/校验 — 第 5 行只说"python 指已安装固定依赖的当前解释器",但后续命令没有任何 python --version 或 venv 激活断言。多人/多机环境下 python 解析到哪个解释器完全依赖 PATH,可能静默跑在错误依赖上,产出的 report/SHA 还照样"通过"。
建议:在命令块首行加护栏,例如 python -c 'import sys; assert sys.version_info[:2] == (3,12), sys.executable',或直接引用 python3.12。

🟡 放弃环境变量间接层,削弱可复现性 — 旧写法 SCRATCHV_PYTHON/SCRATCHV_CC/SCRATCHV_QEMU 可显式锁定 venv 与工具链;新写法改为"由运行入口自动发现",Zig/QEMU 的版本与路径取决于宿主机状态,跨机器结果不可比、失败难定位,与本页"数值门槛不变、证据可复现"的定位相冲突。
建议:保留环境变量但给默认值(未设置时回退自动发现并打印实际使用的版本/路径),或至少在脚本里把发现到的 Zig/QEMU 版本写入报告元数据。

🟡 与 ../LINUX_REPRODUCTION.md 的一致性需确认 — 变更把"由该指南设置 SCRATCHV_*"改成"python + 自动发现"。若该指南仍导出 SCRATCHV_PYTHON 等变量,两份文档互相矛盾,读者无法判断该信哪个。
建议:确认两个文件在同一 PR 内同步更新,并在本页交叉引用具体小节而非笼统"该指南"。

💭 output/w3-ci-evidence-audit-RUN_ID 是字面占位符 — 同段其他路径均用 "$W3_RUN_ID",此处 RUN_ID 未加 $,读者无法判断是需手动替换还是脚本 bug。建议统一为 ${W3_RUN_ID} 或加注释说明。

💭 引号风格不一致 — 原写法 "$SCRATCHV_PYTHON" 有引号,新写法 python 无引号;无空格无实际风险,但建议统一(如变量名含空格的未来场景)。

💭 第 5 行表述含糊 — "已安装固定依赖的当前解释器"未说明依赖从何而来(venv?pip --user?)。建议指明来源与激活步骤,避免读者自行猜测环境装配方式。


📁 docs/llm-deploy-v1.0/W3/README.md

🔴 Cross-doc drift risk — The intro still points readers to ../LINUX_REPRODUCTION.md ("先完成 [Linux 统一环境与资产准备]"). If that guide still documents/sets SCRATCHV_PYTHON/SCRATCHV_CC/SCRATCHV_QEMU, the two docs now contradict each other. A reader following the Linux guide then running this snippet will see stale env vars with no consumer. Update both sides in the same PR, or add a one-line note here that SCRATCHV_* are no longer needed.

🟡 python is ambiguous — "已安装固定依赖的当前解释器" still leaves it unclear which interpreter is meant (system python? venv? python3? a specific version?). Since the doc earlier pins "Python 3.12", consider writing it as python (a 3.12 interpreter with the pinned deps installed, on PATH and active in the same shell) — otherwise the "same Bash session" guarantee is weakened.

🟡 Silent auto-discovery failure mode — "Zig 和 QEMU 由运行入口自动发现" moves configuration from explicit flags to implicit search. Two concerns:

  • If discovery fails, the failure must be loud and actionable (path searched, expected name, how to override). Without reading the script it's unclear whether the user gets a clear error or a cryptic "command not found" later.
  • Removing --cc/--qemu from the snippet is fine if the flags are gone; if they still exist for CI/dev override, mention them once so this doc isn't the only place documenting the interface.

🟡 Reproducibility regression — The prior form pinned exact tool paths via env vars, which made a run's Zig/QEMU versions explicit and diffable. Auto-discovery means the same command can pick different toolchains across machines. The next paragraph says "固定并记录实际完整 SHA" for the model source — consider extending that to record the resolved Zig/QEMU versions so an output/w3-team-preparation-new report is reproducible, not just re-executable.

💭 Nit — "运行入口" is vague; name the script (run_w3_preparation.py) for searchability.


📁 docs/llm-deploy-v1.0/W3/独立复现与验收清单.md

Code Review: W3 独立复现与验收清单.md

🔴 [正确性] --cc / --qemu 参数移除但脚本未确认更新

第 5 行声称 "Zig 和 QEMU 由运行入口自动发现",run_w3_preparation.py 的 --cc "$SCRATCHV_CC" --qemu "$SCRATCHV_QEMU" 被删除。如果脚本本身尚未实现自动发现逻辑,所有复现步骤都会失败。请确认脚本端已同步修改。

🟡 [可复现性] python 替代 $SCRATCHV_PYTHON 削弱环境确定性

原变量显式绑定到已验证的 Python 3.12 解释器路径;新写法依赖 PATH 解析。多版本环境下 python 可能指向 3.11/3.13,且 -X utf8 和 -B 等标志无法保证生效。建议至少加一行守卫:

test "$(python -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')" = "3.12"

🟡 [可复现性] editable install 不适合复现场景

python -m pip install -v -e ".[llm-deploy]"

-e 意味着代码变更即时生效,复现者无法区分"安装时快照"和"运行时改动"。考虑改为 --no-build-isolation + 非 editable 安装,或加注释说明为何需要 editable。

🟡 [文档一致性] "自动发现" vs "PATH 要求" 口径矛盾

第 5 行说 Zig/QEMU "由运行入口自动发现",但依赖章节又说 "PATH 中的系统工具 qemu-system-riscv64"。如果 PATH 是前提条件,"自动发现"只是简化说法,应在首次出现时即说明。

💭 [文档] "兼容入口" 含义不明

"requirements/qwen3-small-probe.txt 仅保留上述 extra 的兼容入口" — 兼容入口是指 pip 仍可从该文件安装、还是该文件仅作为重定向文档?建议一句话说明读者该如何使用它。


📁 docs/llm-deploy-v1.0/W4/README.md

Review: W4 README.md (新增文档)

🟡 数值门槛定义存疑

numeric:qemu-full-qwen3 — 仅用 max_abs < 1e-3 + rtol=0(纯绝对误差)在 28 层 FP32 累积路径上可能过松。28 层 matmul + softmax 的误差随深度非线性增长,1e-3 绝对误差对 logits 空间(值域可达数十)意味着相对误差可能达到 ~1%。

建议:补充一个 rtol 门槛(如 rtol < 1e-4)或注明此阈值已基于 reference 实测校准并给出校准方法,否则未来无法判断该值是否合理。

🟡 EL F 大小上限过于宽松

100,000,000 bytes(100MB)用于"无大权重"的 ELF 上限太宽。Qwen3-0.6B 的权重在外部文件中,生成代码本身应该是 MB 级别。100MB 上限几乎无法捕获"权重意外内联"之类的回归。

建议:收紧到实测值的合理倍数(如 2×实际大小),并说明预期量级。

🟡 替代验证的警告不够突出

"前缀检查点、Host C 诊断、离线 audit、构建成功、top-1 一致均不能替代完整 QEMU 数值门槛" — 这段关键免责声明埋在验收标准之后的普通段落中,容易在快速浏览时被忽略。

建议:移到验收标准表格内作为备注,或用 blockquote 加粗。

💭 日期与提交引用

文中出现 2026-10-15 和 8f726507c539607331f6b3599f2be811205a3e86 等具体引用。若此文档与代码同 PR 提交,这些引用应在合入时由 CI 或 reviewer 验证有效性;否则容易漂移。考虑标注"截至本文档编写时"或加自动校验。

💭 术语未定义

"执行身份"(execution identity)概念未在本文件或引用文件中定义。验收记录要求引用该概念但读者无法追溯其含义。建议在首次出现处加简要脚注或链接到定义处。

💭 "共享修复"未指明

"保留 W4 扩展及共享修复" — 读者无法判断这些修复是什么。建议附 PR 列表或指向 changelog。



⚠️ 未审查的文件

  • docs/llm-deploy-v1.0/W4/evolution.md
  • docs/llm-deploy-v1.0/W4/reports/full-hart-comparison-2026-10-22.json
  • docs/llm-deploy-v1.0/W4/reproduction.md
  • docs/llm-deploy-v1.0/W4/runtime-contract.md
  • docs/llm-deploy-v1.0/W4/softsim-optimization-2026-10-22.md
  • docs/llm-deploy-v1.0/W4/validation.md
  • docs/llm-deploy-v1.0/开发计划.md
  • probes/w2_qwen3_parse/README.md
  • probes/w3_attention/README.md
  • probes/w3_attention/run.py
  • probes/w3_common.py
  • probes/w3_full_preflight/README.md
  • probes/w3_layer_diff/README.md
  • probes/w3_qwen3_full/EVIDENCE.md
  • probes/w3_qwen3_full/LOCALIZE.md
  • probes/w3_qwen3_full/README.md
  • probes/w3_qwen3_full/run.py
  • probes/w3_qwen3_medium/README.md

…ndencies

Sync upstream/main at 8f72650. W3 was squash-merged with the same content already present in W4; retain every existing W4 code and workflow change. Update the W4 dependency baseline without changing historical validation evidence.
Preserve W3 virtualenv and Linux reproduction fixes while adding optional
1/2/4/auto harts, doorbell/WFI waits, Softmax row execution and finite checks,
MatMul tile and column-panel options, and bounded UART/QMP event handling.

Keep single-hart and original-layout defaults. Reduce redundant CI coverage
without dropping real RV64 gates. Preserve the completed numeric comparisons;
validate the final high-FD wait and installation-documentation fixes locally.
Integrate upstream ScratchV-Compiler#114 (5171b59) for hosted Ubuntu test/benchmark runners
and complete-history checkout. Preserve W4 small-QEMU acceptance, explicit
full-model gates, and delegated generic coverage.

Validation: 172 workflow/routing checks passed; no model execution.
@yuki-328 yuki-328 changed the title feat(w4): 完整 Qwen3 外置权重与 RISC-V/QEMU 前向验证 feat(w4): 完整 Qwen3 外置权重、多 hart 执行与验证优化 Oct 22, 2026
@yuki-328
yuki-328 marked this pull request as ready for review October 22, 2026 07:17
@jizhenjun
jizhenjun merged commit 61bded3 into ScratchV-Compiler:main Oct 22, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants