# moxwebgpu
**Repository Path**: thousand-code-crafts/moxwebgpu
## Basic Information
- **Project Name**: moxwebgpu
- **Description**: ⚡ MoX + WebGPU: a tiny, zero-dependency WebGPU compute (GPGPU) framework — typed tensors, raw WGSL kernels, and a lazy compute graph.|GitHub 主仓库 github.com/codecloud-dev/moxwebgpu:Issue/PR 请到 GitHub 提交;本仓库为国内只读镜像,自动同步
- **Primary Language**: TypeScript
- **License**: MIT
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-10-11
- **Last Updated**: 2026-11-14
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
> **🌐 主仓库在 GitHub** — [`codecloud-dev/moxwebgpu`](https://mox-site.pages.dev/go?r=moxwebgpu) 是唯一主源:Issue、Pull Request、功能讨论请统一提交到 GitHub。[Gitee 镜像](https://gitee.com/thousand-code-crafts/moxwebgpu) 仅供国内高速只读访问,每小时从 GitHub 自动同步。
moxwebgpu
中文 · English · 📖 文档站(中/EN 一键切换) · 🚀 在线演示
⭐ 如果 moxwebgpu 对你有用,欢迎点个 Star —— 它能让更多人在浏览器里跑起 GPU 计算!
## 🐛 欢迎来“批斗”我
> 这是个刚起步的项目,**bug 肯定有,而且不少**。我不装完美——
> 你踩到的每一个坑、每一个槽点,都是帮我把它养好的机会。
- 💥 遇到崩溃 / 黑屏 / 跑不起来?→ [提个 Bug 报告](https://mox-site.pages.dev/go?r=moxwebgpu&p=issues)
- 💡 有想要的功能?→ [开个需求](https://mox-site.pages.dev/go?r=moxwebgpu&p=issues)
- 🗯️ 单纯想吐槽、挑刺?→ 也欢迎开 issue,标签随便打 😄
每个 issue 我都会看,能修的尽快修。一起把它从“能跑”养到“好用” 💪
> **同一份源码,浏览器运行、Node 构建与测试。** 没有独立显卡的机器上,用 Chrome 自带的 SwiftShader 软件渲染也能把 27 个真实 WebGPU 端到端测试全部跑绿——这是 moxwebgpu 与大多数「纸面 WebGPU 项目」最大的不同:**它的每一行 GPU 代码都被真实验证过**。
目录(点击展开)
- [项目概览](#项目概览)
- [关于本项目](#关于本项目)
- [为什么需要 moxwebgpu](#为什么需要-moxwebgpu)
- [三层架构](#三层架构)
- [安装](#安装)
- [快速上手](#快速上手)
- [统一 API 参考](#统一-api-参考)
- [浏览器在线训练实战](#浏览器在线训练实战)
- [移动端 GPU 支持](#移动端-gpu-支持)
- [算子清单](#算子清单)
- [数据类型与内存布局](#数据类型与内存布局)
- [错误处理与调试](#错误处理与调试)
- [性能与基准](#性能与基准)
- [测试与质量保证](#测试与质量保证)
- [浏览器演示](#浏览器演示)
- [项目结构](#项目结构)
- [开发指南](#开发指南)
- [路线图](#路线图)
- [FAQ](#faq)
- [参与进来](#参与进来)
- [支持我们](#支持我们)
- [许可证](#许可证)
---
## 📦 项目概览
**moxwebgpu** = **MoX** + **WebGPU**:一个面向浏览器的 **WebGPU 通用计算(GPGPU)框架**。它把 WebGPU 底层繁琐的适配器管理、管线构建、缓冲区生命周期、数据读回全部封装起来,对外暴露三层递进式 API:
| 你想要 | moxwebgpu 给你的 | 一句话示例 |
| ----- | ------------------------------- | ------------------------------------------------------ |
| 快速做计算 | **Tensor 层** —— 类型化张量 + 链式算子 | `gpu.tensor([1,2,3]).add(1).sum().item()` |
| 省心做优化 | **Lazy 计算图** —— 整链一次下发、中间缓冲自动回收 | 六个算子串起来也只 dispatch 一次 |
| 完全控制 | **Kernel 层** —— 直接跑原始 WGSL | `gpu.kernel(wgsl).run([bufA, bufB], { elements: 64 })` |
| 关键指标 | 数值 |
| ----- | ------------------------------------------------ |
| 运行时依赖 | **0**(纯 TypeScript) |
| 产物 | ESM + CJS + IIFE(浏览器全局 `MoxWebGPU`)+ 完整 `.d.ts` |
| 数据类型 | `f32` / `i32` / `u32` |
| 内置算子 | 30+(逐元素 / 归约 / 矩阵 / 形状 / NN / 类型转换) |
| 测试 | 66 单元测试 + **27 个真实 GPU 端到端测试** + 微基准 |
| 最低环境 | 支持 WebGPU 的浏览器(Chrome / Edge 113+);Node ≥ 18(构建) |
> **moxwebgpu 适合谁**:需要在浏览器里做矩阵运算、图像处理、信号处理、ML 前向推理、并行数值计算,又不想手写一屏 WebGPU 样板代码的你。
> **moxwebgpu 不做什么**:不做 WebGL 回退(WebGPU 是底线)、暂不做训练侧自动微分(在路线图上)、不绑定任何 UI 框架。
---
## 💡 关于本项目
moxwebgpu 是一个独立的开源库:把浏览器里「本该简单」的 WebGPU 通用计算能力,认真重造一遍。
| 项目 | 状态 | 一句话定位 |
| :--: | :--: | --- |
| **moxwebgpu** | 已上线(本仓库) | **WebGPU 通用计算框架 —— 浏览器里的张量与计算图** |
---
## 🤔 为什么需要 moxwebgpu
WebGPU 的 compute pipeline 能力极强,但裸用它做一次向量加法,你要亲手闯过五关:
| # | 你要亲手做的事 | 容易踩的坑 |
| :- | ---------------------------------------------- | ------------------------------------------- |
| 1 | `requestAdapter` → `requestDevice` → 队列管理 | 上下文样板代码一写一屏,拿错 adapter 直接崩 |
| 2 | 写 WGSL、建 `ShaderModule`、拼 bind group layout | uniform 对齐规则隐蔽;**布局错了不报错,dispatch 变 no-op** |
| 3 | 手动分配 / 复用 / 销毁 storage buffer | 忘销毁就泄漏;复用错就是脏数据;池子写不好性能反而降 |
| 4 | staging buffer + `copyBufferToBuffer` + map 读回 | 读回流程繁琐,同步语义搞错就读到半截数据 |
| 5 | 每个形状重新建 pipeline | 反复 dispatch 时编译开销白白流失 |
其中第 2 关的「静默失败」最阴险:**WebGPU 的 validation 错误不会抛异常**,只会让对象悄悄变 invalid、dispatch 变成 no-op,你盯着满屏的 0 毫无头绪。moxwebgpu 在开发期就栽过这些坑(WGSL `shared` 保留字、uniform 数组 stride 两种后端不一致、const-expression 禁止 ±Infinity),**坑全部沉淀成了框架的内置防御**(见[错误处理与调试](#错误处理与调试))。
**moxwebgpu 把五关全部关进框架里,你只需要关心「算什么」。**
---
## 🏗️ 三层架构
```text
┌───────────────────────────────────────────────────────────────────┐
│ Tensor 层 —— 统一链式 API(你所写的) │
│ │
│ gpu.tensor([1,2,3]).add(1).relu().mul(10).sum().item() │
└──────────────────────────────┬────────────────────────────────────┘
│ 每个算子只「建节点」,不执行
┌──────────────────────────────▼────────────────────────────────────┐
│ Lazy 计算图 —— 拓扑排序 · 一次下发 · 引用计数回收 │
│ │
│ • 全链构建成 DAG,读回时一次性 topo 排序逐节点执行 │
│ • 中间 buffer 在消费者计数归零的瞬间归还内存池 │
│ • 已执行的节点缓存结果,重复读回不重算 │
└──────────────────────────────┬────────────────────────────────────┘
│ 按 BindingSpec 解析绑定、UBO 走池
┌──────────────────────────────▼────────────────────────────────────┐
│ Core —— BufferPool · PipelineCache · Kernel(逃生舱) │
│ │
│ • BufferPool:2 的幂字节桶,storage / uniform 严格分池 │
│ • PipelineCache:按 WGSL 哈希缓存 compute pipeline │
│ • getCompilationInfo() 显式捕获 shader 编译错误,拒绝静默 no-op │
└───────────────────────────────────────────────────────────────────┘
```
### 🔹 一次 `.add(1).sum().item()` 的完整生命周期
1. `gpu.tensor([...])` 上传数据到池内 storage buffer(Tensor 持有,惰性)。
2. `.add(1)` → 在计算图上挂一个 `add-scalar` 节点,**未执行**。
3. `.sum()` → 再挂一个两阶段归约节点(两个 kernel step)。
4. `.item()` → 触发执行:
- 从根节点做**拓扑排序**;
- 每个节点:从池里拿输出 buffer → 编码 uniform → 组 bind group → **一次** `dispatchWorkgroups`;
- 中间 buffer 的消费者计数减到 0 的那一刻,立刻归还内存池;
- 归约结果经 staging buffer 读回 CPU,返回标量。
5. 整条链共 **3 次 kernel dispatch**(add、归约 phase1、phase2),中间大 buffer 0 泄漏。
更深的实现细节(WGSL 模板、uniform 字节表、调度算法)见 **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)**。
---
## 📦 安装
> ✅ **已发布到 npm**:包名 `@codecloud-dev/moxwebgpu`(当前 `version: 1.1.3`),OIDC 免 token 发布流程已配好(见 `.github/workflows/publish.yml`)。可直接用下方「方式二」安装;也可走「方式三」从源码构建。
### 🌐 方式一:浏览器 `
```
IIFE 产物暴露全局 `MoxWebGPU`,内含 `mox`、`MoxContext`、`Tensor`、`Kernel` 等全部导出。
### 🔹 方式二:npm(Node / 打包器)
> 包名带 scope:`@codecloud-dev/moxwebgpu`(已发布到 npm registry)。
```bash
npm install @codecloud-dev/moxwebgpu
# pnpm add @codecloud-dev/moxwebgpu / yarn add @codecloud-dev/moxwebgpu
```
```ts
import { mox } from '@codecloud-dev/moxwebgpu'; // ESM
// const { mox } = require('moxwebgpu'); // CJS
```
### 🔹 方式三:从源码构建
```bash
git clone https://github.com/codecloud-dev/moxwebgpu.git
cd moxwebgpu
pnpm install # 安装依赖(TypeScript / tsup / vitest / playwright-core)
pnpm build # 产物输出到 dist/
```
---
## 🚀 快速上手
以下示例默认 `const gpu = await mox.init();` 已执行。
### 🔹 1. 第一个张量
```ts
const a = gpu.tensor([1, 2, 3, 4]); // 一维,自动推断 shape=[4]
const m = gpu.tensor([[1, 2, 3], [4, 5, 6]]); // 二维,shape=[2,3]
const t = gpu.tensor(flatData, { shape: [128, 128] }); // TypedArray + 显式形状
```
### 🔹 2. 链式调用与惰性求值
```ts
// 写法像 NumPy,执行像 CUDA 图
const r = await gpu.tensor([1, 2, 3, 4])
.add(1) // [2,3,4,5]
.relu()
.mul(10) // [20,30,40,50]
.sum() // 归约
.item(); // 140 —— 读回时整条链才执行,且只执行一次
```
### 🔹 3. 广播
```ts
const A = gpu.tensor([[1, 2, 3], [10, 20, 30]]); // [2,3]
await A.add(gpu.tensor([1, 2, 3])).toArray();
// 行广播 → [2,4,6, 11,22,33]
await A.mul(gpu.tensor([2, 3])).toArray();
// 列广播 → [2,4,6, 30,60,90]
await A.add(gpu.tensor([1, 2])).toArray();
// ❌ 抛错:形状不合法绝不静默广播
```
### 🔹 4. 矩阵乘法
```ts
const a = gpu.tensor([[1, 2], [3, 4]]);
const b = gpu.tensor([[5, 6], [7, 8]]);
await a.matmul(b).toArray(); // [19, 22, 43, 50]
// 16×16 workgroup 分块;[512,512] 级别同样一条命令
```
### 🔹 5. 归约与 softmax
```ts
const x = gpu.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]);
await x.sum().item(); // 36 全局归约 → [1]
await x.sum(-1).toArray(); // [10, 26] 按最后一轴 → [2]
await x.sum(0).toArray(); // [6, 8, 10, 12] 按第 0 轴 → [4]
const t3 = gpu.tensor(Array.from({ length: 24 }, (_, i) => i), { shape: [2, 3, 4] });
await t3.sum(1).toArray(); // [12,15,18,21,48,51,54,57] —— 3D 中间轴也行,负轴从末尾数
await x.max().toArray(); // [8]
await x.argmax().item(); // 7(首见优先)
await x.softmax().toArray();
// [0.032, 0.087, 0.237, 0.644, ...] —— 减最大值的数值稳定实现,逐行和恒为 1
```
### 🧮 6. 形状操作
```ts
const v = gpu.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
const m = gpu.tensor([[1, 2, 3], [4, 5, 6], [7, 8, 9]]); // 3×3
await v.slice(2, 4).toArray(); // [2,3,4,5](start=2, size=4)
await m.slice([1, 1], [2, 2]).toArray(); // 2D 块切片 → [[5,6],[8,9]]
await gpu.tensor([[1, 2], [3, 4]]).concat(gpu.tensor([[5, 6]]), 0).toArray();
// [1,2,3,4,5,6] —— axis 0 拼接;多 chunk 一次直写输出
const w = v.reshape([2, 5]); // 零拷贝视图,不产生 GPU 计算
```
### 🔤 7. 类型转换
```ts
await gpu.tensor([1.7, 2.2, -3.9]).cast('i32').toArray(); // [1, 2, -3](向零截断)
gpu.tensor([1, 2]).toFloat().dtype; // 'f32'
```
### ⚙️ 8. 原始 Kernel(逃生舱)
```ts
const k = gpu.kernel(`
@group(0) @binding(0) var a: array;
@group(0) @binding(1) var b: array;
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) gid: vec3u) {
b[gid.x] = a[gid.x] * 2.0 + 1.0;
}`);
const a = gpu.tensor([1, 2, 3, 4, 5]);
const out = gpu.pool.acquire(5, 'f32'); // GpuDataBuffer,elements = 5
// 传入 GpuDataBuffer(而非 .buffer):readback 长度按 buf.elements 取,返回精确的 5 个元素
const res = await k.run([a.data, out], { elements: 5 });
// Float32Array(5) [3, 5, 7, 9, 11]
```
`k.run()` = dispatch + 读回一步到位;`k.dispatch(buffers, [wx, wy, wz])` 只下发不读回。WGSL 照常走管线缓存。
> 读回长度说明:`run()` 优先使用传入的 `GpuDataBuffer.elements` 作为读回元素数(池化 buffer 会按 2 的幂字节桶向上取整,直接读原始尺寸会多读 padding)。若传入裸 `GPUBuffer`,则回退到其原始尺寸。
### 📦 9. 资源管理
```ts
gpu.destroy(); // 归还并销毁全部池化 buffer + device(页面卸载前调用)
t.destroy(); // 单个张量释放(通常不需要,池会自动回收中间结果)
```
---
### 🧠 10. 自动微分(反向模式 / 训练)
moxwebgpu 1.0 起内置**反向模式自动微分**,直接叠加在现有惰性计算图上——`OpDef` 只是纯元数据 + codegen,每个算子附带一个 `backward`,反向图天然复用同一套算子,只有当你读取梯度时才上 GPU。
```ts
import { mox } from '@codecloud-dev/moxwebgpu';
const gpu = await mox.init();
const x = gpu.tensor([1, 2, 3, 4]).withGrad(); // 标记可微叶子
const loss = x.mul(x).sum(); // L = Σ x²
loss.backward(); // 反向传播
console.log(await x.grad.toArray()); // [2, 4, 6, 8] = dL/dx
```
三个要点:
- **`.withGrad()`**:标记该叶子张量需要梯度(其余叶子默认不计)。
- **`.backward()`**:从标量 loss 出发,逆拓扑序传播,把梯度填进每个 `requiresGrad` 叶子的 **`.grad`**。整个过程只建惰性图,**不碰 GPU**,直到你 `await x.grad.toArray()`。
- **广播正确**:二元算子的梯度会用 `sumTo` 自动归约回较小操作数的形状;`sum/mean/softmax` 的梯度用 `expand` 复制回去。
```ts
// 一个最小线性层的前向 + 反向
const W = gpu.tensor([[0.1, 0.2], [0.3, 0.4]]).withGrad();
const inp = gpu.tensor([1, 1]);
const pred = W.matmul(inp); // [2]
const loss = pred.mul(pred).sum(); // Σ pred²
loss.backward();
console.log(await W.grad.toArray()); // dL/dW,形状与 W 一致
```
**已支持反向的算子**:加/减/乘/除(含标量、含广播)、neg/abs/exp/log/sqrt/square/relu/sigmoid/tanh、matmul、sum/mean(全局与任意轴)、softmax(沿末轴,数值稳定)。
> 路线图中 layernorm / embedding / conv1d、pass 融合、Web Worker 运行属于 **1.0.x 后续规划**,本版未做——给后续更新留空间。
---
### 🚀 浏览器在线训练实战(无需安装,浏览器里当场训一个模型)
> **这是 moxwebgpu 最被低估的能力**:它不止能做单次 GPGPU 计算,还能在**浏览器里跑完整的自动微分 + 梯度下降训练循环**——数据不用出浏览器、不依赖任何后端,笔记本 / 手机 / 树莓派只要有 WebGPU 就能训。配合前面说的「前端直接 `