想象你开了一家网页餐厅。WebGL 时代,浏览器只给你一台只能做西餐的固定小灶台;想做中餐、想做甜品,都得勉强挤在同一台设备上。WebGPU 来了以后,后厨全面升级:不再限定某几道菜,而是给你一个真正的中央厨房——成百上千个专业厨师(GPU 核心)随时待命,你只需要把菜谱写清楚,总管一声令下,所有灶台同时开工。对于 AI 从业者来说,这就意味着:网页不再只是展示页面,而是能直接跑模型推理的“应用现场”。 这篇文章会带你走进这座中央厨房:先看 WebGPU 和 WebGL 的差别,再看计算着色器怎么写、AI 模型怎么部署、WebAssembly 怎么配合,最后聊聊性能、兼容性和真实案例。

岗位关联

对 AI 从业者来说,掌握 WebGPU 浏览器端推理,等于把模型部署半径从服务器扩展到全球数十亿浏览器终端,让 AI 应用更省成本、更重隐私、更快触达用户。

目录
  1. 可视化演示
  2. 前世今生
  3. 并行计算基础
  4. 计算着色器
  5. AI模型推理
  6. WASM协作
  7. 性能兼容性
  8. 落地案例
  9. AI 应用场景
  10. Python 演示
  11. 常见误区
  12. 面试题

可视化演示

通过交互式滑块调节检验统计量与显著性水平,实时观察p值变化与拒绝域判定,理解假设检验的决策逻辑。

本节配有交互动效(进入视口后自动加载,约 3KB)。

右尾假设检验 红色区域为p值,即检验统计量右侧的尾部概率 绿色虚线为临界值 z(α),超过则拒绝H₀ p = P(Z ≥ z | H₀) 调节统计量观察p值变化

前世今生

想象你在网页餐厅后厨工作。WebGL 时代,浏览器只给了一台“固定小灶台”:它擅长给三角形上色、做纹理贴图,但你没办法让它自由地做通用计算。AI 推理需要的矩阵乘法、卷积,都得伪装成图形绘制指令,像硬把中餐菜谱塞进西餐烤箱,别扭又低效。

WebGPU 改变了这一切。它由 W3C 的“浏览器 GPU”工作组推动,参考了 Vulkan、Metal、DirectX 12 这些现代图形 API 的设计,把渲染管线和计算管线统一在同一套抽象下。对 AI 推理来说,最大的变化是:网页终于可以直接把数据交给 GPU 的成百上千个计算核心,让它们同时干活。

WebGL 基于 OpenGL ES 2.0,本质是为图形渲染设计的“半开放 API”;WebGPU 则是面向现代 GPU 的“全开放 API”。你可以把它理解为:过去只能点套餐,现在能进中央厨房自己写菜谱。这个“能写菜谱”的能力,正是浏览器端 GPU 推理的技术地基。

并行计算基础

中央厨房之所以出菜快,不是某一位厨师手速惊人,而是配菜、切墩、掌勺、装盘同时开工。GPU 也是这样:它不是用一个大核心硬算,而是用大量小核心同时处理不同数据。这种思路叫“数据并行”。

WebGPU 把这种并行抽象成两层概念:线程(thread)和工作组(workgroup)。一个线程就是一位厨师,负责处理一小块数据;一组线程组成一个工作组,类似一个料理台。工作组内的线程可以共享一部分显存,方便协作完成更大的任务。多个工作组再组合起来,铺满整个 GPU。

这里有一个最简单的数学关系:

除了线程,还要理解显存。GPU 不能直接读取 JavaScript 对象,所有数据都要先放进“缓冲区(Buffer)”,像食材先搬到备料区。CPU 和 GPU 之间搬运数据是有成本的,所以做 AI 推理时要尽量减少来回搬运。理解了分组和缓冲区,就走进了中央厨房的核心区域。

工作线程总数=工作组数×每个工作组线程数\displaystyle \text{工作线程总数} = \text{工作组数} \times \text{每个工作组线程数}
这句话的真正含义是:GPU 的并行规模不是写代码时随意定的,而是由“组数”和“每组人数”两个旋钮共同决定。
  1. 工作线程总数最终会有多少个 GPU 线程同时参与计算。
    工作线程总数\text{工作线程总数}
  2. 工作组数GPU 把线程分成几个小组,像厨房分成几个料理台。
    工作组数\text{工作组数}
  3. 每个工作组线程数每个料理台上同时开火的厨师数量。
    每个工作组线程数\text{每个工作组线程数}
  4. 乘积关系总线程数等于组数乘以每组人数。
    工作线程总数=工作组数×每个工作组线程数\displaystyle \text{工作线程总数} = \text{工作组数} \times \text{每个工作组线程数}

计算着色器

有了中央厨房,还需要一张菜谱。这张菜谱就是“计算着色器(Compute Shader)”。它不是 JavaScript 代码,而是写给 GPU 上每个工人看的批量操作说明:每个线程拿到自己的编号,对某块数据执行同样的运算。

WebGPU 的着色语言叫 WGSL(WebGPU Shading Language)。它运行在 GPU 上,语法风格接近 Rust,但职责非常单一——算数、取值、写回。JavaScript 负责“调度”,WGSL 负责“干活”,两者像老板和厨师的分工。

写计算着色器时,最常遇到的问题是:数据有 1000 个元素,但每个工作组只有 64 个线程,要派发几次?答案用向上取整:

WGSL 还支持工作组内共享内存。工作组内的线程可以把中间结果放进一块快速共享区域,像几个厨师共用一个操作台传菜。“内存模型”决定了哪些数据在显存里、哪些数据在共享内存里,这对矩阵乘法这类算子的性能影响很大。

派发次数=⌈数据元素数工作组大小⌉\displaystyle \text{派发次数} = \left\lceil \frac{\text{数据元素数}}{\text{工作组大小}} \right\rceil
向上取整的意思是:哪怕最后一组只有一个人,也得单独开一桌,不能漏掉任何一个数据。
  1. 数据元素数需要被处理的样本总量,比如 1000 个像素或 1000 个矩阵元素。
    数据元素数\text{数据元素数}
  2. 工作组大小每个工作组里并行线程数,比如 64。
    工作组大小\text{工作组大小}
  3. 向上取整除法结果若不是整数,就进一位,保证所有数据都有线程处理。
    ⌈数据元素数工作组大小⌉\displaystyle \left\lceil \frac{\text{数据元素数}}{\text{工作组大小}} \right\rceil
  4. 派发次数JavaScript 调用 dispatchWorkgroups 时填写的次数,等于开几桌。
    派发次数\text{派发次数}

AI模型推理

在餐厅里,预训练好的 AI 模型就像一份预制菜料包。它不能直接倒进锅里,要先解冻、分装、按自家灶台重新摆盘。把 PyTorch 或 TensorFlow 模型变成浏览器能用的格式,就是“模型转换”。

WebGPU 推理的典型流程是:先把模型导出为 ONNX 或 GGUF 这类开放格式,再把权重二进制文件加载进 GPUBuffer,最后用 WGSL 把卷积、矩阵乘法、激活函数写成计算着色器。浏览器没有默认的 conv2d 函数,这些算子都要靠着色器自己实现。

整个推理过程可以拆成三段:

实际工程中,还会把相邻算子融合:比如“卷积 + ReLU”写进同一个着色器,像把“切菜 + 焯水”合并成一道工序,减少读显存和写显存的次数。权重加载时也常用量化,把 float32 变成 int8,像把食材提前切小块冷冻,省空间、省带宽。

单次推理时延≈数据上传耗时+计算耗时+结果回读耗时\displaystyle \text{单次推理时延} \approx \text{数据上传耗时} + \text{计算耗时} + \text{结果回读耗时}
这条公式提醒我们:GPU 算得再快,如果数据在 CPU 和 GPU 之间传得慢,整体时延依然下不来。
  1. 数据上传耗时把输入图片或文本特征搬进 GPU 显存的时间。
    数据上传耗时\text{数据上传耗时}
  2. 计算耗时GPU 执行所有计算着色器的时间。
    计算耗时\text{计算耗时}
  3. 结果回读耗时把推理结果从显存拿回 CPU 的时间。
    结果回读耗时\text{结果回读耗时}
  4. 总时延三段耗时叠加,决定一次推理从输入到输出花了多久。
    单次推理时延≈数据上传耗时+计算耗时+结果回读耗时\displaystyle \text{单次推理时延} \approx \text{数据上传耗时} + \text{计算耗时} + \text{结果回读耗时}

WASM协作

中央厨房再强,也需要一个账房先生管理菜单、记账、处理复杂的订单格式。在浏览器端,这个角色就是 WebAssembly(WASM)。它运行在 CPU 上,不是 GPU 的替代品,而是 WebGPU 的最佳搭档。

WASM 擅长做“杂活”:解析 ONNX 文件、做分词、跑 JSON 配置、处理量化/反量化、写复杂的 if-else 逻辑。这些任务不仅并行度低,还可能充满分支,放到 GPU 上反而浪费。WebGPU 则适合做“大活”:矩阵乘法、卷积、逐元素激活,数据规整、计算密集。

两者通过 JavaScript 调度协作。JS 负责创建 GPU 设备、管理缓冲区、提交命令;WASM 负责把模型数据整理成 GPU 能吃的格式;WebGPU 只专注批量并行计算。数据共享的关键是 ArrayBuffer:GPU 计算完的结果映射回 CPU 内存,WASM 可以直接读取,再交给 JS 更新页面。

这种分工很像真正的餐饮公司:账房(WASM)精确处理琐碎事务,厨房(WebGPU)批量生产硬菜,老板(JavaScript)居中调度。对 AI 推理来说,WASM 负责“理解模型”,WebGPU 负责“计算模型”,才是一个完整的前端推理引擎。

性能兼容性

中央厨房虽然快,但不是每家餐厅都有条件安装。WebGPU 的性能再漂亮,也要看浏览器支不支持、用户设备强不强。

从性能上看,WebGPU 计算着色器执行矩阵乘法、卷积时,通常远快于 WebGL 的图形伪装方案,也比纯 WASM/CPU 快一个数量级。但性能上限往往不是算力,而是带宽:数据上传、结果回读、纹理拷贝都会拖慢整体。所以最佳实践是“尽量少搬数据,尽量多融合算子”。

从兼容性看,WebGPU 已逐步在各大浏览器中推出,但版本差异和平台差异依然存在。上线前必须用 navigator.gpu 做特性检测,不支持时降级到 WebGL2 模拟计算,或者直接用 WASM + CPU 推理。这个降级策略很像保留一套传统灶台,万一新厨房不能用,餐厅今天也不能停业。

评估并行收益时,Amdahl 定律是最常用的公式:

所以,做浏览器端 AI 推理时,先看瓶颈在哪:如果模型又大又依赖矩阵乘,GPU 收益明显;如果只是读 JSON、做字符串处理,WASM 可能就足够了。

S=1(1−p)+pN\displaystyle S = \frac{1}{(1-p) + \frac{p}{N}}
它告诉我们:如果一个任务的 90% 能并行,即便核心数无限多,加速比也不会超过 10 倍。串行部分永远是天花板。
  1. p(可并行占比)任务中能被 GPU 并行的部分所占比例。
    pp
  2. N(并行规模)GPU 核心数或并行线程数。
    NN
  3. 1-p(串行占比)必须靠 CPU 顺序执行的部分。
    1−p1-p
  4. S(加速比)使用并行后比纯串行快了多少倍。
    S=1(1−p)+pN\displaystyle S = \frac{1}{(1-p) + \frac{p}{N}}

落地案例

现在,已经有不少“餐厅”真的用上了中央厨房。最常见的是图像超分:用户上传一张模糊照片,浏览器把图片送进 WebGPU,计算着色器并行处理每个像素块,几秒钟就得到高清版本,全程不需要把照片传到服务器。

另一个典型场景是实时人像分割。摄像头画面进入网页后,一个只有几 MB 的轻量模型在浏览器内完成推理,GPU 把每一帧的前景和背景分开,就能实现直播间背景虚化、虚拟背景替换。数据不上传,不仅省了服务器成本,也保护了用户隐私。

端侧小模型也在兴起。像 WebLLM 这类开源项目,已经能用 WebGPU 在浏览器中跑几亿参数的小型语言模型。虽然还比不上服务器端千亿大模型,但对于文档摘要、邮件润色、本地翻译等场景,已经足够实用,而且完全离线。

未来,随着 WebGPU 兼容性越来越广、量化工具越来越成熟,“打开网页就拥有一个本地 GPU 推理引擎”会成为标配。前端 AI 工程师的岗位,也会像当年移动端工程师一样,从“页面切图”升级为“端侧推理优化”。

AI 应用场景

浏览器端实时人像分割

阶段:推理部署与端侧优化

解决的问题:传统做法是把摄像头帧上传到服务器做人像分割,延迟高、带宽贵,还容易把隐私画面暴露给云端。AI 直接部署在浏览器里,通过 WebGPU 的并行计算完成逐帧推理,既省流量又保护隐私。

具体案例:视频会议网页版中,用户开启“背景虚化”功能。前端加载一个约 5MB 的人像分割 ONNX 模型,WebGPU 用计算着色器处理每一帧,只在用户本地完成语义分割,再把前景和人像重新合成。

网页图片超分辨率

阶段:模型转换 + 浏览器端推理

解决的问题:传统修图工具要么依赖桌面软件,要么把图片传到云端处理。WebGPU 推理让图片超分直接在网页完成,适合隐私敏感的照片批量处理场景。

具体案例:在线文档平台集成了“图片高清化”按钮。用户上传 1080p 图片,前端先转换成加权张量,再用 WGSL 编写卷积与亚像素卷积算子,GPU 并行重建出 4K 分辨率,整个过程不离开浏览器。

端侧小型语言模型对话

阶段:模型量化 + 端侧推理

解决的问题:服务器端大模型并发成本高,且有数据出境风险。把数亿参数的小模型量化后部署在浏览器,通过 WebGPU 跑 Transformer 算子,实现完全离线的轻量对话。

具体案例:本地文档问答工具在浏览器中加载量化到 int8 的 3B 模型,WASM 负责分词和采样,WebGPU 负责多头注意力与 FFN 矩阵计算,用户提问后本地生成回答。

Python 演示

python31 行
import math  class GPUSim:    """用 Python 模拟 WebGPU 计算着色器的一次 dispatch。"""     def __init__(self, data, group_size=4):        self.data = data        self.group_size = group_size        self.group_count = math.ceil(len(data) / group_size)        self._output = [0.0] * len(data)        self.task_count = 0     def fused_relu_bias(self, bias):        """每个线程处理一个元素: y = max(0, x + bias)。"""        for g in range(self.group_count):            start = g * self.group_size            end = min(start + self.group_size, len(self.data))            for idx in range(start, end):                self._output[idx] = max(0.0, self.data[idx] + bias)                self.task_count += 1        return self._output  if __name__ == '__main__':    x = [-2, -1, 0, 1, 2, 3, 4, 5, 6]    sim = GPUSim(x, group_size=4)    y = sim.fused_relu_bias(0.5)    print("group_count =", sim.group_count)    print("output =", y)    print("task_count =", sim.task_count)
目的:用可运行 Python 代码模拟 WebGPU 的“分组派发 + 融合算子”思想,帮助理解 GPU 上每个线程做同一件事、但作用在不同数据上的并行模式。
  1. self.group_count = math.ceil(len(data) / group_size)计算需要派发多少个工作组,对应 WebGPU 的 dispatchWorkgroups 次数。
  2. def fused_relu_bias(self, bias):定义一个融合算子:偏置加法与 ReLU 在同一个 kernel 中完成。
  3. for g in range(self.group_count):外层循环模拟分组派发,每个工作组处理一段连续数据。
  4. end = min(start + self.group_size, len(self.data))防止最后一组越界,对应 WGSL 中的边界检查。
  5. self._output[idx] = max(0.0, self.data[idx] + bias)线程核心计算,等价于 compute shader 里的 y = max(0, x + bias)。
  6. self.task_count += 1统计实际处理了多少元素,方便验证并行任务是否覆盖完整。

常见误区

误区WebGPU 不就是 WebGL 换个名字吗?API 差不多,优化思路也一样。

正解WebGL 面向传统图形渲染,计算必须伪装成绘制命令;WebGPU 同时提供渲染管线和计算管线,计算着色器可以自由做通用并行计算。它更像从“只能做西餐的小灶台”升级成“想做什么菜都行的中央厨房”,而不是换了个菜单。

为何常见:两者都叫 Web 图形 API,很多同学学过 WebGL 后以为 WebGPU 只是版本号提升。

误区WebGPU 这么强,AI 推理全部搬到浏览器,服务器再也不用买 GPU 了。

正解浏览器端受显存、带宽、模型体积限制,只适合中小模型。千亿大模型、复杂微调、海量并发仍需要服务器。更常见的架构是“端侧做隐私敏感的轻量模型,云端做重模型兜底”。

为何常见:看到 WebGPU 跑 LLM 的 Demo 很惊艳,忽略了 Demo 只跑小型模型且只做一次推理。

误区写 WGSL 就像写 JS,定义几个数组,调循环处理数据就行。

正解WGSL 运行在 GPU 上,不能操作 DOM、不能创建 JS 对象,只能读写 Buffer 中的纯数据。它必须使用显存地址、工作组共享内存等概念,相当于“厨师只能碰备料台上的食材,不能跑出厨房接电话”。

为何常见:前端同学习惯了 JS 的灵活对象模型,第一次接触 GPU Shading Language 很容易按 CPU 思维写代码。

误区把 `.pt` 或 `.pth` 权重文件下载到浏览器,WebGPU 就能直接读出来做推理。

正解GPU 不认识 PyTorch 的 Python 对象格式。必须先转成 ONNX、GGUF 等开放格式,再解析权重、绑定到 GPUBuffer,最后逐层实现算子。这就像冷冻预制菜拿到中央厨房,必须拆包装、解冻、分盘后才能上灶。

为何常见:很多人混淆“训练框架的权重格式”和“推理引擎的部署格式”。

误区既然 Chrome 能跑 WebGPU,那用户浏览器肯定都能跑,直接上线即可。

正解WebGPU 的浏览器支持仍在推进中,不同设备、不同平台的表现差异很大。上线前必须用 navigator.gpu 做特性检测,并准备 WebGL2 或 WASM 降级方案。

为何常见:开发者用自己的最新 Chrome 测试通过,忽略了真实用户可能还在旧版浏览器或缺少 GPU 驱动的环境。

面试题

Q1. WebGPU 相比 WebGL 最核心的突破是什么?

单选题 · easy

  • A.更好的网页动画样式
  • B.支持通用并行计算← 正确答案
  • C.更快的 JavaScript 解析
  • D.更强的 CSS 渲染引擎

答案:B。WebGPU 引入了计算着色器,允许 GPU 做通用计算,AI 推理正是依赖这一点。动画样式、JS 解析、CSS 渲染都不是 WebGPU 的核心定位。

Q2. 在 WebGPU 中,计算着色器使用的着色语言是?

单选题 · easy

  • A.GLSL
  • B.HLSL
  • C.WGSL← 正确答案
  • D.Rust

答案:C。WGSL 是 WebGPU 官方的着色语言,运行在 GPU 上。GLSL 是 WebGL/OpenGL 的语言,HLSL 是 DirectX 的语言,Rust 是通用 CPU 编程语言。

Q3. 关于 GPU 并行计算,下列哪个说法正确?

单选题 · easy

  • A.单核频率越高越好
  • B.核心越多并行越强← 正确答案
  • C.内存越大速度越快
  • D.线程越多一定有收益

答案:B。GPU 的优势是大量核心同时处理数据,所以“核心越多并行越强”正确。线程增多不一定有收益,还受显存带宽和串行部分限制。

Q4. 在 WebGPU 中,dispatch 的含义是?

单选题 · mid

  • A.把数据从 CPU 拷贝到 GPU
  • B.向 GPU 提交一次计算任务← 正确答案
  • C.创建一组顶点缓冲区
  • D.把显示画面输出到屏幕

答案:B。dispatchWorkgroups 表示派发计算任务给 GPU 的工作组执行,类似厨房总管喊一声“开工”。拷贝数据是 buffer 操作,顶点缓冲区和画面输出属于图形渲染。

Q5. 部署 AI 模型到 WebGPU 推理前,通常先做什么?

单选题 · mid

  • A.把权重转换为 ONNX 或 GGUF 格式← 正确答案
  • B.用 Python 重新训练一遍模型
  • C.删除所有无关权重参数
  • D.把模型封装成浏览器插件

答案:A。模型先转成 ONNX 或 GGUF 等部署格式,才能被前端解析和加载。重新训练没有必要,随意删权重会破坏精度,浏览器插件也不是部署格式。

Q6. WebGPU 中工作组(workgroup)的主要作用是?

单选题 · hard

  • A.管理浏览器标签页的显存占用
  • B.定义线程间的共享内存和调度粒度← 正确答案
  • C.限制页面只能调用一个 GPU 设备
  • D.代替 JavaScript 处理网络请求

答案:B。工作组是 GPU 调度的基本单位,组内线程可以共享显存、协作计算。它不负责标签页显存管理,也不限制 GPU 设备数量,更不能替代 JS 做网络请求。

Q7. 某计算任务可并行部分占比为 p,串行部分无法并行,使用 N 核 GPU 后理论加速比 S 是?

单选题 · hard

  • A.S = 1 / ((1-p)+p/N)← 正确答案
  • B.S = (1-p)+p/N
  • C.S = 1 / (1-p) + N
  • D.S = p + (1-p)/N

答案:A。Amdahl 定律中,总耗时是串行部分 (1-p) 加上并行部分被 N 除后的 p/N,所以加速比是总耗时倒数。这就像再多人洗碗,收银只有一个人也会限制整体速度。

Q8. WebGPU 适合在浏览器端做 AI 推理的原因有哪些?

多选题 · mid

  • A.可以利用 GPU 并行计算← 正确答案
  • B.数据不需要上传到服务器← 正确答案
  • C.所有浏览器都已完全支持
  • D.能直接加载 PyTorch 权重

答案:AB。GPU 并行和本地计算是 WebGPU 推理的核心优势。但并非所有浏览器都支持,PyTorch 权重也要先转换成 ONNX/GGUF 才能被 GPU 解析。

Q9. WebAssembly 与 WebGPU 配合时,WASM 适合承担哪些工作?

多选题 · hard

  • A.解析模型格式和预处理数据← 正确答案
  • B.调度 GPU 计算资源和显存
  • C.做复杂的标量逻辑和 IO 编排← 正确答案
  • D.替代 GPU 执行大规模矩阵乘法

答案:AC。WASM 擅长模型解析、分词、量化等 CPU 杂活。调度 GPU 资源和显存是 WebGPU/JS 的职责,大规模矩阵乘法应该交给 GPU 并行执行,WASM 替代不了。

Q10. 关于 WebGPU 浏览器端推理的性能优化,哪些做法是合理的?

多选题 · extreme

  • A.把多次小矩阵运算合并成一个大算子← 正确答案
  • B.每帧重新创建所有缓冲区和管线
  • C.用 int8 量化权重减少显存和带宽← 正确答案
  • D.禁止使用 compute shader 只靠 fragment shader 并行

答案:AC。算子融合减少显存读写,量化降低权重体积和带宽,都是常见优化。每帧重建缓冲区和管线会带来严重开销;只靠 fragment shader 绕路做通用计算,正是 WebGPU 要抛弃的旧模式。