WebGPU — 浏览器中的下一代图形与AI计算

Author Avatar
via
发表:2026-07-11 09:01:02
修改:2026-07-11 09:01:00

引言:从 WebGL 到 WebGPU 的范式转变

过去十余年,WebGL 一直是浏览器中 3D 图形和 GPU 计算的基石。但随着现代 GPU 架构的演进和 AI 工作负载的爆发式增长,WebGL 基于 OpenGL ES 的设计已经显得力不从心。WebGPU 作为继任者,不仅仅是一次 API 升级,而是一次彻底的范式重新设计——它直接映射现代 GPU 的工作方式(显式管线、命令缓冲、绑定组),并原生支持通用计算(Compute Shader),为在浏览器中运行 AI 推理打开了大门。

2026 年,WebGPU 已在 Chrome、Edge、Safari 技术预览中稳定支持,Firefox 也在逐步推进。本文将深入解析 WebGPU 的核心架构、与 WebGL 的关键差异,以及如何用它在前端实现轻量级 AI 推理。

一、WebGPU 核心架构解析

1.1 显式管线模型

WebGL 的管线相对隐式——你设置状态,GPU 驱动在背后做很多事。WebGPU 选择了显式控制:

  • Render Pipeline 对象:管线状态(着色器、混合模式、拓扑结构等)在创建时一次性指定,运行时只需绑定。这消除了大量状态切换带来的性能损耗。
  • Command Encoder:所有渲染指令先编码到命令缓冲区,再一次性提交到 GPU 队列。这种"录制再回放"的模式与 Vulkan/Metal 一致,让驱动层有更多优化空间。
  • Pass Encoder:渲染通道和计算通道分别由 RenderPassEncoder 和 ComputePassEncoder 管理,职责清晰。

1.2 绑定组(Bind Group)

这是 WebGPU 与 WebGL 最显著的设计差异之一。在 WebGL 中,uniform 的设置是命令式的——逐个设置每个变量。WebGPU 引入了 Bind Group 概念:

// 创建 bind group layout
const bindGroupLayout = device.createBindGroupLayout({
  entries: [{
    binding: 0,
    visibility: GPUShaderStage.COMPUTE,
    buffer: { type: 'storage' }
  }]
});

// 创建 bind group(绑定实际资源)
const bindGroup = device.createBindGroup({
  layout: bindGroupLayout,
  entries: [{ binding: 0, resource: { buffer: storageBuffer } }]
});

一个 Bind Group 是一组资源的集合(buffer、texture、sampler),可以整体绑定到管线上。这意味着资源组合可以预先创建并复用,大幅减少绘制调用前的状态设置开销。

1.3 Compute Shader:通用计算的钥匙

WebGL 无法直接做通用 GPU 计算(只能通过纹理渲染的 hack 绕路)。WebGPU 原生支持 Compute Shader,可以直接读写 storage buffer,这使得矩阵运算、卷积、注意力机制等 AI 核心操作可以在 GPU 上高效执行。

@compute @workgroup_size(64)
fn main(
  @builtin(global_invocation_id) id: vec3<u32>,
  @group(0) @binding(0) var<storage, read> a: array<f32>,
  @group(0) @binding(1) var<storage, read> b: array<f32>,
  @group(0) @binding(2) var<storage, write> result: array<f32>,
) {
  let idx = id.x;
  if (idx >= arrayLength(&a)) { return; }
  result[idx] = a[idx] + b[idx];
}

上面的 WGSL 代码展示了一个简单的向量加法 compute shader。workgroup_size(64) 表示每个工作组包含 64 个线程,GPU 会并行调度大量工作组来完成计算。

二、WebGPU vs WebGL:关键差异

特性WebGL 2.0WebGPU
底层 APIOpenGL ES 3.0映射现代 GPU(Vulkan/Metal/D3D12)
通用计算不支持(需 hack)原生 Compute Shader
资源绑定逐个 uniform 设置Bind Group 批量绑定
管线状态运行时状态机预编译 Pipeline 对象
命令录制即时模式命令缓冲编码+提交
着色器语言GLSLWGSL(WebGPU 专用)
错误处理GL 错误(同步检查)Validation 错误 + Device lost 事件

这些差异不仅仅是 API 层面的——它们反映了 GPU 编程十余年来的最佳实践沉淀:显式优于隐式,预编译优于运行时检查,批量操作优于逐个设置。

三、WGSL:为 Web 而生的着色器语言

WebGPU 没有使用 GLSL 或 SPIR-V,而是推出了全新的 WGSL(WebGPU Shading Language)。设计目标包括:

  • 安全性:内存安全、类型安全,编译时就能捕获大部分错误
  • 简洁性:语法参考 Rust 和 TypeScript,对前端开发者友好
  • 可移植性:在所有后端(Vulkan、Metal、D3D12)上行为一致

WGSL 的类型系统比 GLSL 更严格:类型转换必须显式,向量分量访问有明确的 swizzle 规则。这在一开始可能让习惯了 GLSL 的开发者觉得繁琐,但在大型项目中能显著减少运行时错误。

// WGSL 示例:顶点着色器
@vertex
fn vs_main(
  @location(0) position: vec3<f32>,
  @location(1) uv: vec2<f32>,
) -> VertexOutput {
  var output: VertexOutput;
  output.position = uniforms.mvp * vec4<f32>(position, 1.0);
  output.uv = uv;
  return output;
}

四、在浏览器中运行 AI:WebGPU + 轻量推理

4.1 为什么 WebGPU 适合 AI

AI 推理的核心计算模式——矩阵乘法、卷积、注意力——天然适合 GPU 并行计算。WebGPU 的 Compute Shader 让这些操作可以直接在浏览器中 GPU 加速执行,无需后端服务器。这对于:

  • 隐私敏感场景:图像分类、语音识别等数据不离开设备
  • 低延迟交互:无需网络往返,即时响应
  • 离线可用:加载模型后断网仍可推理

4.2 实际案例:在浏览器中运行 Transformer

以一个轻量 GPT 模型为例,关键步骤如下:

步骤一:加载模型权重

将量化后的模型(如 ONNX 或自定义格式)加载为 ArrayBuffer,然后创建 GPUBuffer:

const weightBuffer = device.createBuffer({
  size: weightData.byteLength,
  usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_DST,
});
device.queue.writeBuffer(weightBuffer, 0, weightData);

步骤二:实现注意力计算

Self-attention 的核心是 Q × K^T → softmax → × V。每个步骤可以是一个 compute pass,也可以融合为单个 shader:

@compute @workgroup_size(16, 16)
fn attention(
  @group(0) @binding(0) var<storage, read> Q: array<f32>,
  @group(0) @binding(1) var<storage, read> K: array<f32>,
  @group(0) @binding(2) var<storage, read> V: array<f32>,
  @group(0) @binding(3) var<storage, read> params: Params,
  @group(0) @binding(4) var<storage, read_write> output: array<f32>,
) {
  let row = global_id.x;
  let col = global_id.y;
  if (row >= params.seq_len || col >= params.dim) { return; }
  
  // 计算注意力分数
  var score: f32 = 0.0;
  for (var k: u32 = 0u; k < params.head_dim; k++) {
    score += Q[row * params.head_dim + k] * K[col * params.head_dim + k];
  }
  score = score / f32(params.head_dim);
  
  // softmax 需要两遍:先求最大值和求和,再归一化
  // ...(省略 softmax 实现)
  
  output[row * params.dim + col] = score;
}

步骤三:调度与推理循环

function runInference(tokens) {
  // 编码命令
  const encoder = device.createCommandEncoder();
  const pass = encoder.beginComputePass();
  pass.setPipeline(attentionPipeline);
  pass.setBindGroup(0, attentionBindGroup);
  pass.dispatchWorkgroups(
    Math.ceil(seqLen / 16),
    Math.ceil(dim / 16)
  );
  pass.end();
  
  // 提交并等待完成
  device.queue.submit([encoder.finish()]);
  // 读取结果...
}

4.3 性能优化策略

  • 批量化:将多个 token 的计算合并到一次 dispatch 中
  • 量化:使用 int8 或 float16 减少显存占用和带宽压力
  • 算子融合:将 QKV 投影、softmax 等操作融合到单个 shader
  • 异步管线:在 GPU 计算时 CPU 可以准备下一批数据
  • Workgroup 内存:利用 shared memory 减少全局内存访问

五、实际性能表现与限制

在 2026 年的中端设备上(如 M2 MacBook Air 或 Snapdragon 8 Gen 3 手机),WebGPU 运行量化的 1B 参数模型可以达到以下性能:

  • 首 token 生成延迟:200-500ms
  • 后续 token 速度:15-40 tokens/s
  • 模型加载时间:1-3 秒(取决于量化级别和模型大小)

但 WebGPU 仍有限制:

  • 显存限制:浏览器对 GPU 内存有配额,通常 2-4GB
  • 调试困难:GPU 端的错误信息仍不如 CPU 直观
  • 跨平台差异:不同 GPU 厂商的驱动行为存在微妙差异
  • 浏览器支持:Firefox 还在逐步完善中

六、未来展望

WebGPU 正在扩展更多能力:

  • WebGPU Subgroups:更细粒度的线程协作,提升 wave-level 优化
  • WebGPU Ray Tracing:实时光线追踪在 Web 上的可能
  • 与 WebNN 融合:WebNN 提供更高层级的 AI 算子 API,WebGPU 作为底层加速后端

更重要的是,WebGPU 正在改变"前端"的定义。前端不再只是 UI 层——它正在成为完整的计算平台。当浏览器可以原生调度 GPU 进行矩阵运算,"前端 AI"就不再是一个概念演示,而是一个可行的生产方案。

总结

WebGPU 带来了三件关键事物:显式的 GPU 控制模型、原生的通用计算能力、以及为 Web 环境量身定制的着色器语言。对于前端开发者,它打开了一扇新门——从图形渲染到 AI 推理,GPU 的能力首次在浏览器中完整开放。对于 AI 工程师,它提供了一个零部署成本的推理运行时——模型加载即用,无需后端基础设施。

如果你还没有尝试过 WebGPU,现在是最好的时机。从最简单的 compute shader 开始,感受 GPU 在浏览器中迸发算力的那一刻——那是一种全新的体验。

评论