{
  "lead": "SIMD（单指令多数据）让一条 CPU 指令同时处理一组数据：一个 128 位寄存器可以装 4 个 f32、8 个 u16 或 16 个 u8，一次加法就把它们全部加完。WebAssembly 从 2021 年起在主流浏览器里支持 128 位 SIMD。这个页面把同样的三个算法各写两遍——普通标量 Rust 和用 <code>core::arch::wasm32</code> 显式写的 SIMD 版本——在浏览器里现场跑分，并逐项核对两边的结果。",
  "formulas": [
    [
      "[a₀ a₁ a₂ a₃] + [b₀ b₁ b₂ b₃] = [a₀+b₀ … a₃+b₃]",
      "一条 f32x4_add 指令完成 4 次加法"
    ]
  ],
  "terms": [
    [
      "向量点积（f32 × 4）",
      "每次从两个数组各读 4 个 f32，乘完累加到 4 个独立的部分和里，最后把 4 个部分和相加。求和顺序和标量版不同，浮点舍入误差也就不同：两者都和 f64 精确值比较，误差都在 1% 以内才算通过。有趣的是 SIMD 版往往更准——4 个部分和各自更小，每次累加损失的精度更少。"
    ],
    [
      "图像叠加（u8 × 16）",
      "两张 RGBA 图片逐通道相加，超过 255 就截断为 255（饱和加法）。标量版每次处理 1 个字节并判断是否溢出；SIMD 版用 <code>u8x16_add_sat</code> 一条指令处理 16 个字节，溢出截断由硬件完成，所以加速最明显。校验和也用「两两相加并扩宽」的指令向量化计算。"
    ],
    [
      "曼德博集合（f32 × 4 像素）",
      "相邻 4 个像素放进同一个寄存器一起迭代。难点是各像素逃逸的时刻不同：用比较指令得到一个「仍在迭代」的掩码，只给这些通道计数，全部逃逸才退出循环。4 个像素要等最慢的那个，所以实际加速低于 4 倍；边界越复杂的区域，相邻像素迭代次数差得越多，加速越少。运算顺序和标量版完全相同，所以迭代次数逐像素一致。"
    ],
    [
      "只给 SIMD 函数开启 simd128",
      "如果整个 crate 用 <code>-C target-feature=+simd128</code> 编译，LLVM 会把「标量」循环也自动向量化，对比就失去意义。这里只在 SIMD 函数上标注 <code>#[target_feature(enable = \"simd128\")]</code>，标量代码保持标量。"
    ],
    [
      "特性检测",
      "只要 .wasm 里含有 SIMD 指令，不支持的浏览器连编译都会失败，没法在 WASM 里自己检测。所以页面先用 <code>WebAssembly.validate</code> 校验一个 31 字节的 SIMD 小模块，通过后再加载真正的模块。"
    ]
  ],
  "flow": [
    [
      "js",
      "页面先检测 SIMD 支持，然后调用 <code>simd_prepare(n, 像素数)</code>，让 Rust 用固定种子生成两组 f32 向量和两张随机图片（数据留在 WASM 内存里，避免每次复制）。"
    ],
    [
      "rust",
      "每个测试有标量和 SIMD 两个导出函数（如 <code>dot_scalar</code> / <code>dot_simd</code>），计算同样的结果；<code>dot_exact()</code> 用 f64 算出参考值。"
    ],
    [
      "js",
      "JS 对每个函数先预热一次，再计时 5 轮取中位数，核对两边结果，并把 SIMD 算出的曼德博集合画到 Canvas 上。"
    ]
  ],
  "perf": [
    "实测（桌面 Chromium，「中」规模）：点积快 2.2~2.5 倍，图像叠加快 6~8 倍，这个曼德博区域快约 1.5 倍（在 Node 中渲染整个集合的全景图时约 1.9 倍）。",
    "点积和图像叠加的数据量很大，速度最终受内存带宽限制，测几次结果会有浮动；曼德博集合纯计算，结果最稳定。",
    "浏览器为了安全把 <code>performance.now()</code> 的精度限制在约 0.1ms，所以很快的测试每轮会重复调用多次，再取平均。",
    "需要 Chrome 91+、Firefox 89+、Safari 16.4+（iOS 16.4+）。更早的浏览器会显示不支持的提示。"
  ],
  "src": [
    [
      "crates/algorithms/simd/src/lib.rs",
      ""
    ],
    [
      "www/simd/index.js",
      ""
    ]
  ]
}
