← 文章 / 开源项目
HuggingFace博客 13小时前 · 2026-09-02 01:19:26 · 4 阅读

Hugging Face推出@huggingface/kernels:为本地AI提供200多个WebGPU Kernels

Hugging Face WebAI 团队的首要目标之一,是让浏览器端推理尽可能快、尽可能易用。要实现这一目标,需要多层协同:模型需要适合浏览器的表示形式,运行时需要构建高效的执行计划,而底层的各项 GPU 操作也必须充分适配不同设备和浏览器实现的特性。

今天,我们发布了这项工作的第一层基础:@huggingface/kernels。这是一个轻量级库,可从 Hugging Face Hub 加载并运行经过优化的 WebGPU kernels;与此同时,我们还在 huggingface.co/webgpu-kernels 上发布了首批 207 个 kernels

这批 kernels 覆盖了各种机器学习架构和工作负载中使用的操作。更重要的是,每个 kernel 都以完整且版本化的软件包形式发布:接口、shader 模板、正确性测试用例、基准测试用例和使用说明,全部集中在 Hub 上。

我们还推出了 Fleet,这是一套在浏览器中运行的 GPU 基准测试与测试工具,可在你的硬件上执行并评估这些 kernels。除了展示你自己设备上的结果,Fleet 也为社区提供了一个渠道,让大家贡献来自各种设备的性能和正确性数据,而这些设备是传统测试实验室不可能全部覆盖的。在你同意的前提下,每次运行都会新增私密证据,帮助我们发现错误结果、极慢场景等问题,改进 kernel 变体,并针对真实世界中的硬件做出更好的优化决策。

核心内容

  • 207 个 WebGPU kernels:以独立仓库的形式发布在 webgpu-kernels 组织下,采用 Apache-2.0 许可证。
  • JavaScript 加载器@huggingface/kernels,可直接从 Hub 下载、准备并运行 kernels。
  • 明确的契约与可复现的证据:每个 kernel 都提供 manifest、正确性测试、基准测试用例和 WGSL shader 模板。
  • Fleet:一款基于浏览器的基准测试工具,通过汇集真实世界 GPU 的正确性与性能数据,帮助我们改进 kernels 及其变体。

为什么要从 kernel 入手?

模型要在浏览器中运行,最终都会转化为一系列 GPU 操作:矩阵乘法、归一化、卷积、注意力原语、量化、数据布局转换等。WebGPU 通过可移植 API,让这些操作能够在现代浏览器中运行;WGSL 则为执行这些操作的 shader 提供了统一语言。

不过,可移植并不意味着高性能。两个 shader 即使实现相同操作、产生相同输出,在不同加速器上的表现也可能截然不同。Workgroup 大小、内存访问模式、向量化、数据类型和融合策略,都会影响性能。最佳方案还可能随着输入形状、设备、浏览器和可用 WebGPU 特性的变化而改变。

因此,kernel 是实现浏览器高性能推理的基础层。上层运行时的效率,取决于它所调度的操作。将这些操作分别做成可发现、可测试、可基准测试并支持版本管理的组件,我们就能独立改进底层,同时为上层保持稳定的接口契约。

不只是 shader,而是 kernel 仓库

集合中的每个 kernel 都有自己的仓库和 kernel 卡片。卡片会记录该操作的语义、输入、输出、属性、支持的数据类型、源文件,以及一个可以直接运行的 @huggingface/kernels 示例。

例如,ai.onnx.Add 实现了支持多向广播的逐元素加法。这是神经网络中最简单、也最常见的操作之一,从残差连接到偏置相加都能用到。它的卡片记录了两个输入、广播后的输出形状、支持的数据类型,以及针对不同形状和设备提供的变体。

Files in the ai.onnx.Add WebGPU kernel repository
ai.onnx.Add 仓库将 manifest、正确性和基准测试用例,以及 WGSL shader 模板整合在一起。

在卡片背后,仓库还包含了理解和评估该实现所需的各种产物:

  • manifest.json 是操作契约的权威定义,规定了输入、输出、属性、类型约束和形状推导规则。
  • metadata.json 记录 kernel 标识符、摘要和来源信息。
  • test.json 包含正确性测试用例,用于验证实现是否符合预期行为。
  • bench.json 包含基准测试和调优用例,用于模拟评估 kernel 时采用的工作负载。
  • *.wgsl.jinja 文件包含参数化的 WGSL 实现,用于针对特定请求和设备生成 shader。

这种结构让 shader 成为可复用的软件制品:无需阅读 WGSL 即可查看接口,正确性和性能测试用例也会随实现一起发布;加载指定版本时,只需明确指定版本,不必依赖未进行版本管理的文件 URL。对于开发自定义 WebGPU kernel,或将这些操作集成到自有运行时的开发者来说,我们的 kernel 也可以作为参考实现。

从 Hub 加载 kernel

从 npm 安装软件包:

npm install @huggingface/kernels@preview

运行这些 kernel 需要使用支持 WebGPU 的浏览器。WebGPU 是否可用取决于浏览器、操作系统、GPU 和驱动程序。你可以在 JavaScript 中通过 "gpu" in navigator 检查其可用性。

@huggingface/kernels 负责连接 kernel 仓库与应用程序。使用 Hub 仓库 ID 和契约版本调用 getKernel,然后将带有类型信息的输入数据和张量形状传给返回的函数。下面是一个简单的偏置相加示例:

import { getKernel } from "@huggingface/kernels";

const add = await getKernel("webgpu-kernels/ai.onnx.Add", { version: 1 });

const { c } = await add({
  a: {
    data: new Float32Array([1, 2, 3, 4, 5, 6]),
    shape: [2, 3],
  },
  b: {
    data: new Float32Array([10, 20, 30]),
    shape: [3],
  },
});

第二个输入会沿第一个维度进行广播,生成形状为 [2, 3] 的输出。加载器会根据 manifest 契约和输入推导出输出形状及逻辑数据类型,然后自动分配 c

对 6 个浮点数执行加法,是能做到的最小演示。在这种规模下,GPU 往返的开销远高于计算本身。这个示例的重点在于调用方式:面对矩阵乘法(ai.onnx.MatMul)等真正能从优化 kernel 中获益的重量级操作时,调用方式完全不变,只需更换仓库 ID 和输入。

即使是这样简单的操作,也能说明为什么 kernel 需要多个变体。形状相同的加法可以直接采用向量化路径,而带广播的输入则需要不同的索引逻辑。已发布的 Add kernel 为形状相同、向量化广播、标量处理和通用广播分别提供了变体。运行时可以根据当前调用和设备选择合适的实现,同时无需改变面向应用的 API。

version: 1 选项用于选择已发布的kernel 契约第 1 版。它与 ONNX opset、算子的 since_version 以及模型版本彼此独立。将这些概念分开后,应用就能依赖稳定的面向 JavaScript 的契约,而 kernel 的具体实现则可以在其背后持续演进。

kernel 的速度有多快?

那么,优化后的 kernel 到底能带来多大提升?我们在 Apple M4 GPU 上,使用 ONNX Runtime Web 1.30.0-dev.20260826-b1f76d586a,将这套 kernel 与 ORT WebGPU 进行了直接对比。在全部 207 个操作上,我们一共测试了 1,756 个用例,最终保留了双方输出一致且计时可靠的 809 个用例。

在这些对比中,我们的 kernel 按几何平均计算快2.57 倍,按中位数计算快1.90 倍;其中 629 次胜出、176 次落后、4 次持平。下面详细看看其中 4 个常见操作:

操作 对比用例数 我们的 WebGPU Kernel ORT WebGPU 加速比
Add 5 0.064 ms 0.227 ms 3.52x
MatMul 29 0.115 ms 0.131 ms 1.14x
Softmax 12 0.114 ms 0.240 ms 2.11x
LayerNormalization 6 0.061 ms 0.135 ms 2.22x

部分算子的提升幅度要大得多。例如,一个特别棘手的双线性 Einsum 场景(i,ij,j,尺寸为 4096)使用我们的 kernel 只需 0.136 ms,而 ORT WebGPU 需要 1,396 ms,速度提升超过 10,000 倍。对 [256, 4096] 执行按行 CumSum 时,耗时从 4.784 ms 降至 0.016 ms,速度提升了 301 倍。这些都是比较特殊的场景,并不代表所有任务都能获得同样的加速,但它们说明:当通用实现走上慢路径时,专用 kernel 能带来多大的帮助。

我们只统计了 GPU 实际执行计算的时间,不包括加载 kernel、创建 session、上传输入、编译 shader 以及读回输出等准备工作。执行时间很短的任务本来就更难精确测量,而较小的任务还可能受益于 GPU 缓存。因此,这些数字更适合作为有参考价值的对比,而不是对每个应用的性能承诺。

另外,这些结果针对的是单个算子,而不是完整模型。具体性能会因 GPU 和浏览器而异,这也是 Fleet 对于建立更全面的性能画像非常重要的原因。

我们也正在与 ONNX Runtime 团队合作,将这些改进 upstream,让更广泛的 ONNX Runtime Web 生态都能受益。

从单台设备到设备集群

WebGPU 的性能会因 GPU、浏览器和驱动而异,因此单台机器上的结果只能反映部分情况。借助 Fleet,任何人都可以直接在浏览器中运行正确性和性能检查,了解这些 kernel 在自己设备上的表现。

在获得许可后,每次运行都会以隐私方式贡献数据,帮助我们发现特定设备上的问题、比较不同变体并改进选择规则。目标很简单:通过广泛的真实设备覆盖,让这些 kernel 对所有人来说都更快、更可靠。

为 WebAI 构建共享基础

最初发布的 207 个 kernel 只是起点,并非最终形态。将 kernel 独立发布到 Hub 上,为我们提供了一个共享空间,可以检查接口约定、比较不同实现、复现正确性检查并优化性能,而不必把每个 shader 都直接嵌入每个 runtime。

这套内核也是 Hub 更大规模内核生态的一部分:在Kernels 页面上,WebGPU 内核与 CUDA、ROCm、Metal 等平台的内核并列展示,用户可以像探索 Hub 上的其他资源一样,对它们进行筛选、排序和浏览。

The Hub Kernels page filtered to the WebGPU platform, listing the 207 published kernels
Hub 的Kernels 页面按平台筛选后,展示全部 207 个 WebGPU 内核。

这些环节相互促进:

  1. 内核仓库定义透明且带版本管理的操作契约。
  2. @huggingface/kernels让开发者可以通过 JavaScript 轻松加载并运行这些操作。
  3. Fleet 能够在远超传统基准测试实验室覆盖范围的设备上,收集真实世界的数据。
  4. 每次贡献的运行结果都可能暴露故障、为调优提供依据、改进变体选择,并帮助验证未来版本的内核。

这是我们浏览器推理技术栈下一步发展的底层基础。接下来,我们将把这些内核接入更高层的模型工具,持续扩展操作覆盖范围,让整个 WebAI 生态中的本地推理更快、更易用。

欢迎探索WebGPU 内核集合,试用 @huggingface/kernels,并加入 Fleet,贡献来自你设备的运行数据,帮助我们让这些内核惠及所有用户。

原始来源: HuggingFace博客

评论 (0)