返回博客
AI 工程

WebGPU 入门:在浏览器中运行深度学习推理的性能优化指南

📅 2025.11.10 ⏱️ 15 min 👤 Eric Pan

概述

WebGPU 正在彻底改变浏览器中高性能计算的格局。作为 WebGL 的继任者,它不仅提供了更现代的图形 API,更重要的是暴露了强大的 Compute Shader 能力——这意味着我们终于可以在浏览器中高效地运行深度学习推理,而无需依赖 WebAssembly 的 workaround。

作为一名在学习视觉模型开发的学生,我对"能否在浏览器中跑模型"这个问题特别感兴趣。本文将从零开始,带你了解 WebGPU 的核心概念,并通过实际的 ML 推理案例,展示如何在浏览器中获得接近原生 GPU 的性能。

WebGPU 的出现标志着浏览器从 "图形渲染工具" 升级为 "通用 GPU 计算平台",这是 Web 平台能力的一次质的飞跃。

WebGPU 核心概念

WebGPU 是由 W3C GPU Working Group 开发的全新 Web API,设计灵感来自 Vulkan、Metal 和 Direct3D 12。与 WebGL 相比,它提供了更底层的 GPU 访问能力,同时保持了 Web 平台的安全性和可移植性。

WebGPU 的核心抽象包括:

最关键的区别在于:WebGPU 原生支持 Compute Shader,这是一个通用的 GPU 并行计算接口。在 WebGL 时代,我们只能通过 "将计算伪装成渲染" 的 hack 来利用 GPU 的并行能力,而 WebGPU 让这一切变得自然而高效。

Compute Pipeline 搭建

WebGPU 的使用流程遵循一个清晰的模式:请求适配器 - 请求设备 - 创建 Buffer - 编写 Shader - 构建 Pipeline - 提交执行。每一步都是显式的,给你最大的控制权。

与 WebGL 的状态机模型不同,WebGPU 采用命令缓冲区(Command Buffer)模式:先录制所有 GPU 命令,然后一次性提交。这种设计天然适合 ML 推理的批处理场景。

在 ML 推理场景中,典型的工作流程是:

WGSL 着色器编程

WGSL(WebGPU Shading Language)是 WebGPU 的着色器语言,语法类似 Rust,支持向量化操作和共享内存。对于 ML 推理,我们需要将矩阵乘法、激活函数等操作翻译为 WGSL compute shader。

以下是一个使用 Shared Memory Tiling 优化的矩阵乘法 shader,这是 Transformer 模型中最核心的计算操作:

matmul_tiled.wgsl
// Tiled matrix multiplication with shared memory
const TILE: u32 = 16u;
@group(0) @binding(0) var<storage> A: array<f32>;
@group(0) @binding(1) var<storage> B: array<f32>;
@group(0) @binding(2) var<storage, read_write> C: array<f32>;
@group(0) @binding(3) var<uniform> params: vec4<u32>; // M, N, K, _
var<workgroup> tileA: array<array<f32, TILE>, TILE>;
var<workgroup> tileB: array<array<f32, TILE>, TILE>;
@compute @workgroup_size(TILE, TILE)
fn main(
@builtin(global_invocation_id) gid: vec3<u32>,
@builtin(local_invocation_id) lid: vec3<u32>,
) {
let M = params.x; let N = params.y; let K = params.z;
let row = gid.x; let col = gid.y;
var sum = 0.0;
for (var t = 0u; t < K; t += TILE) {
tileA[lid.x][lid.y] = A[row * K + t + lid.y];
tileB[lid.x][lid.y] = B[(t + lid.x) * N + col];
workgroupBarrier();
for (var k = 0u; k < TILE; k++) {
sum += tileA[lid.x][k] * tileB[k][lid.y];
}
workgroupBarrier();
}
C[row * N + col] = sum;
}

这个 tiled 版本利用了 workgroup shared memory,将全局内存访问次数减少了 TILE 倍。在实际测试中,tiled 版本比朴素实现快 8-12 倍。

在浏览器中运行 ONNX 模型

ONNX Runtime Web 是连接 WebGPU 和深度学习模型的桥梁。它将 ONNX 模型中的每个算子映射为 WebGPU compute shader,实现了端到端的浏览器内推理。

核心工作流程包括:

对于 Transformer 模型,ORT Web 还支持 KV Cache 优化,将自注意力的计算复杂度从 O(n²) 降低到 O(n),显著提升长序列推理效率。

GPU 内存管理策略

WebGPU 的内存模型与原生 GPU API 非常相似。Buffer 是 GPU 可见的内存块,关键的优化点在于最小化 CPU 与 GPU 之间的数据传输。

对于 ML 推理场景,推荐以下最佳实践:

模型权重应该在初始化时一次性上传到 GPU,推理过程中只传输输入 tensor。对于 MobileNetV3 级别的模型(约 15MB 权重),初始化上传耗时约 50ms,之后的每次推理只需传输输入图像数据(约 0.6MB)。

内存优化的核心原则:让数据尽可能留在 GPU 上,减少跨设备传输。每一次 CPU-GPU 数据拷贝都是潜在的性能瓶颈。

性能基准测试

我们在三种方案上跑了一系列基准测试,使用相同的 MobileNetV3 模型处理 224x224 的输入图像。测试环境为 MacBook Pro M3 Max + Chrome 125。

WebGPU 的推理速度是 WebGL 的 5.6 倍,是纯 WebAssembly 的 15 倍。更重要的是,WebGPU 的性能在处理更大模型时优势更加明显——对于 BERT-base 级别的模型,差距可以拉大到 20 倍以上。

当然,WebGPU 也有其局限性:浏览器支持尚未完全普及(目前约 78% 的桌面浏览器支持),以及某些旧设备的驱动兼容性问题。但对于面向现代浏览器的 Web 应用来说,WebGPU 已经是 ML 推理的最佳选择。

实战建议与最佳实践

基于我们在生产环境中的经验,总结以下 WebGPU ML 推理的最佳实践:

WebGPU 生态正在快速发展,W3C 规范仍在持续迭代。建议持续关注 Chrome DevRel 博客和 WebGPU Explainer,及时跟进 API 变更和新特性。