7,845
社区成员
发帖
与我相关
我的任务
分享摘要:把 SSE/AVX、x64 汇编或只支持 x86 的构建系统迁移到 ARM64,真正困难的往往不是“翻译出一段能编译的代码”,而是确认语义是否一致、测试是否有效、项目能否完整构建,以及移植后是否真的更快。EasyWoS 将扫描、规范匹配、代码迁移、验证、集成、性能剖析和优化串成一条可审计的工程流水线。本文介绍它的整体方案,并给出一套可以直接照做的快速上手流程。
随着 AI 编码 Agent 的普及,目前最直接的做法,是把整个 x86/x64 项目交给 Codex、Claude Code 等通用 Agent,并提出类似下面的要求:
分析这个项目中的 x86/x64 专用代码,将它移植到 Windows ARM64,
修改构建配置,并完成编译和测试。
Agent 会读取项目源码,搜索 SSE/AVX intrinsic、x64 汇编和架构相关的条件编译,生成 NEON/AArch64 实现,修改 CMake 或 Visual Studio 工程,然后尝试构建和修复错误。相比完全依赖人工逐文件分析,这种方式已经能显著降低迁移的启动成本。
对于规模较小、架构相关代码不多、测试比较完善的项目,直接使用 Agent 往往可以快速得到一个初始 ARM64 版本。开发者不必熟悉每一条 x86 和 ARM 指令,也不需要从零搭建所有代码框架。
但这种方式主要依赖通用模型在当前会话中的临时分析和推理。扫描是否完整、迁移规则是否正确、测试有没有真正覆盖新实现、性能是否发生回退,通常缺少统一的工程约束。这正是复杂项目中需要进一步解决的问题。
直接使用 Agent 进行架构迁移,本质上是把源码分析、方案选择、代码生成和结果验证同时交给一个通用模型。这条路在简单场景里有效,但在真实项目中经常遇到四类问题:
movemask、pcmpestrm、gather、mulhi、pshufb 等 x86 语义,在 NEON 上可能没有直接等价物,甚至需要替换算法。_mm_shuffle_epi8 和 vqtbl1q 的越界清零条件不同,普通样例很容易漏掉边界差异。因此,一个可交付的移植结果至少需要回答下面四个问题:
EasyWoS 的价值,正是把这些问题纳入同一条端到端流水线,而不是只提供若干指令替换表。
EasyWoS 是一套面向 Windows on Snapdragon(ARM64/ARM64EC)的 AI 编码技能树和编排方案。它的目标不是生成一个孤立的补丁,而是把项目从“未经分析的 x64 源码”推进到“已移植、已验证、已实测的 ARM64 构建”。
完整链路可以概括为:
扫描 → 规划 → 规范匹配 → 路由 → 移植 → 单元验证
→ 集成 → 全量构建 → 项目测试 → 自动修复
→ 性能剖析 → 优化 → 经验沉淀
下面是EasyWoS的生命周期描述图:

从职责上看,它可以抽象成五类协作角色:
| 角色 | 主要职责 |
|---|---|
| Spec Agent | 扫描源码、识别迁移项、匹配已有迁移规范并生成任务 |
| Coding Agent | 根据专家技能和规范生成 ARM64/NEON 实现 |
| Test & Fix Agent | 生成验证工程,执行测试并针对失败迭代修复 |
| Profiling Agent | 采集 ETL、分析进程 CPU、生成火焰图 |
| Performance Agent | 从热点追溯根因,优化后重新验证和测量 |
这里的重点不是 Agent 数量,而是职责分离:负责写代码的环节不能自己用一句“看起来没问题”完成验收;每个结论都需要构建、测试或性能证据支撑。
EasyWoS 仓库的核心内容位于 agent/skills/。从架构上可以分为四层。
arm64-port-orchestrator 负责驱动整个项目的生命周期,包括扫描、计划、逐项移植、集成、全量构建、运行项目自带测试、修复失败、性能循环以及最终归档。
它解决的是“如何让整个项目收敛”,而不是直接编写每个内核。
easywos-spec:扫描项目代码,生成YAML文件描述需要移植的代码;匹配专家技能树(skills),生成带规范匹配结果的YAML文件,用于后续做代码移植路由。dispatcher-skill:读取迁移项和规范编号,将任务路由到正确的专家技能。arm64-baseline-porting:在没有具体规范命中时提供兜底约束,例如 Windows ARM64 ABI、弱内存序、NEON 128 位宽度、ARM64EC 兼容和尾部处理规则。匹配过程不是单纯让模型“凭感觉选技能”,而是先由脚本根据源码证据筛选候选规范,再由模型进行语义精化。低置信度条目会被标记为需要复核,而不是悄悄猜测。
真正的迁移知识保存在叶子技能中。当前主要能力包括:
| 技能 | 用途 |
|---|---|
sse-avx-to-neon | 将 SSE/AVX intrinsic 迁移到 NEON,包括 CRC32 的 PCLMULQDQ → PMULL |
intrinsics-x64-to-arm64 | 处理 Windows C++ SIMD 迁移、条件编译守卫和 ARM64 限制 |
asm-x64-to-arm64 | 将内联 x64 汇编或 MASM .asm 转为 AArch64 |
arm64-inlineasm-to-intrinsics | 将 ARM64 NEON 内联汇编改写为可维护的 C/C++ intrinsic,并生成验证工程 |
enable-windows-arm64 | 为 CMake、Visual Studio、Make、Bazel 等构建系统补充 ARM64 配置 |
jit-arm64ec-virtualalloc-fix-skill | 处理 ARM64EC JIT 可执行代码页分配问题 |
arm64-porting-report | 生成结构化的 ARM64 迁移扫描报告 |
每条成熟经验会被写入机器可匹配的 YAML 规范和供智能体理解的 Markdown 配方。后续项目遇到同类代码时,可以复用已经验证过的迁移规则,而不是再次临场发挥。
性能链路由三个技能组成:
etl-generator
↓ 采集 ETL CPU trace
perf-sampling-parser
↓ 进程 CPU 排名 + SpeedScope 火焰图
perf-optimizer
↓ 热点根因 + 源码缺口 + 优化建议/报告
这一层将“代码正确”和“结果可交付”区分开来。只有通过语义验证、真实项目测试和性能对照,迁移才算完成。
性能验证需要管理员权限来启动ETL性能数据的采集。
EasyWoS 要求验证用例在错误实现中能够“失败”,然后再验证正确实现能够通过。
这就是负向控制:如果一个测试从未失败过,就无法证明它真的覆盖了待验证的代码。因为一个始终返回成功、没有链接到新内核或根本没有执行的测试,也会显示为绿色。这在多次yyud移植实践中被反复证实了。
因此,EasyWoS 的判断标准是:
未观察到 Red 的 Green,不算已验证。
性能比较不能拿优化后的 ARM64 内核去对比临时手写的朴素标量函数,而应对比项目真实的回退构建(原始X64代码构建)。否则测出的收益可能只是“SIMD 对朴素循环”的差距,不能说明此次迁移优于项目原有行为。
EasyWoS 同时强调:一个语义正确、但比它替换掉的实现更慢的内核,仍然需要再优化,继续移植。
以下用 zlib-ng 项目举例,展示EasyWoS 的实际收集:
| 收益 | EasyWoS 的做法 | 实践结果 |
|---|---|---|
| 提高移植成功率 | 规范匹配、专家技能分发、验证失败后自动反馈重试 | 将直接移植失败的结果推进为可构建、可验证的 ARM64 实现 |
| 改善 Agent 输出性能 | 在直接移植结果上继续进行规范驱动优化 | 高能力 Agent 提升 9.2%;中等能力 Agent 提升 15.5% |
| 扩大代码覆盖范围 | 按内核家族逐项迁移,补充 NEON、ACLE、PMULL 和标量回退路径 | 移植代码由 409 行增加到 1,011 行,增加 147% |
| 降低正确性风险 | 语义对照测试、Red→Green 负向控制、失败反馈循环 | 相同测试范围下,失败用例由 47 个降为 0 |
| 避免性能回退 | 使用真实回退构建做 A/B 对比,结合剖析结果持续优化 | 整体性能与 upstream 持平,多个关键内核获得提升 |

如上图,zlib-ng 性能实践结果:
| 指标 | 实践结果 |
|---|---|
| 225 项 benchmark 总体几何平均值(相对 upstream) | 0.999×,总体持平 |
| 快于 upstream 的内核数量 | 91 |
1 MiB uncompress 完整 API 路径 | 1.07× |
crc32_copy PMULL 最佳结果 | 1.45× |
adler32 最佳结果 | 1.19× |
以上数据来自特定项目版本、硬件、编译器和测试负载,不代表所有项目都会获得相同幅度的提升。
建议准备以下环境:
交叉编译可以帮助发现构建问题,但无法替代真实 ARM64 机器上的语义验证和性能测量。
执行:
npx skills add qualcomm/EasyWoS/agent --all
也可以使用完整地址:
npx skills add https://github.com/qualcomm/EasyWoS/tree/main/agent --all
仓库更新后可以重新执行安装命令,以获取新增技能和最新迁移规范。
在开始前,最好明确以下信息:
强烈建议先保存一份可复现的 x64 基线结果。它既能帮助排查原有缺陷,也能避免把项目本身的问题误判为 ARM64 移植问题。
最小请求只有一句话:
使用 easywos-skills 将 C:/src/my-project 端到端移植到 ARM64。
Agent 随后会自动选择顶层编排技能。普通用户不需要手工调用匹配器或逐条执行 dispatcher 命令。
流水线通常会生成或维护以下产物:
扫描 YAML
→ <name>-matched.yaml
→ tasks.md
→ 每个内核的验证工程与反馈记录
→ 全量构建/测试证据
→ ETL、SpeedScope 或 HTML 性能报告
重点检查:
code_range exceeds bounds 等警告;NEEDS REVIEW;叶子技能生成代码后,流水线会为迁移项创建测试工程。失败的条目会携带反馈重新分发给同一个专家技能,在预算范围内迭代修复。
单个内核测试通过后,还必须把它接入项目真实构建,再执行:
不要把“单独的 NEON 文件编译成功”当作整个项目已经支持 ARM64。条件编译、运行时分发、构建文件、导出符号和链接方式都可能让正确的内核在真实程序中不可达。
建议至少用下面这张清单验收:
并非所有任务都需要完整流水线。如果只是处理一个明确问题,可以直接描述任务,让 Agent 激活相应技能。例如:
把 src/filter.cpp 中的 SSE/AVX 内核迁移为 ARM64 NEON,并保留 x64 路径。
把 src/x64/kernel.asm 中的 MASM 实现迁移为 AArch64,并生成语义对照测试。
为这个 CMake 项目增加 Windows ARM64 配置,并验证完整构建。
把这段 ARM64 NEON 内联汇编改写为 MSVC 可构建的 intrinsic,配套生成 gtest。
单技能模式适合范围清晰、人工可以审阅的改动;如果涉及多个内核、真实项目集成或性能交付,仍建议使用端到端编排。
可以完成扫描、生成代码和交叉编译,但不能把结果声明为“已验证”。gtest、项目测试和性能分析最终都需要在真实 ARM64 环境运行。
不一定。OpenSpec 主要用于变更编排、阶段门禁和过程留档;单独调用叶子技能或使用无 OpenSpec 流程也可以完成迁移。
首先确认测试是否执行到新代码,其次确认负向控制能让测试变红,最后还要完成真实项目集成和性能对照。EasyWoS 不把“恒绿测试”当作有效证据。
因为 ARM64 可能有更合适的原生指令或算法。例如,某些字符串比较指令在 NEON 上没有直接等价物,强行模拟可能比改用新的 SIMD 扫描算法更慢;某些 multiply-high 场景也更适合使用 AArch64 原生指令。
移动设备在持续负载下可能受到温度和频率变化影响。测试前应预热,两组实验使用相同负载和计时方式,轮次之间留出冷却时间,并报告中位数或多轮统计结果。
函数可能没有执行,也可能被内联、改名或缺少符号。仅凭“火焰图中消失”不能证明优化生效,需要结合可触发该内核的负载、符号配置以及移植前后的对照结果判断。
EasyWoS 尤其适合:
以下场景可能不需要完整流水线:
EasyWoS 解决的不是“让 AI 写出 ARM64 代码”这么单一的问题,而是如何把 AI 生成的架构迁移变成一项可验证、可度量、可复现、可持续积累的工程活动。
它的核心思路可以归纳为四点:
如果你的项目正在面对 SSE/AVX、x64 汇编、ARM64 构建系统或性能回归问题,可以从安装技能并提交一条端到端请求开始:
使用 easywos-skills 将 C:/src/my-project 端到端移植到 Windows ARM64。
项目地址:https://github.com/qualcomm/EasyWoS
标签: ARM64、Windows on ARM、NEON、AI 编程、性能优化