Burn 框架 WebAssembly 推理指南:使用 Flex 与 WebGpu 后端在浏览器中运行深度学习模型

发布时间:2026/9/14 18:36:22
Burn 框架 WebAssembly 推理指南:使用 Flex 与 WebGpu 后端在浏览器中运行深度学习模型 Burn 框架 WebAssembly 推理指南使用 Flex 与 WebGpu 后端在浏览器中运行深度学习模型【免费下载链接】burnBurn is a next generation tensor library and Deep Learning Framework that doesnt compromise on flexibility, efficiency and portability.项目地址: https://gitcode.com/GitHub_Trending/bu/burn本文基于 Burn 官方进阶文档《WebAssembly》讲解如何将 Burn 训练好的模型编译为 WebAssemblyWASM并在浏览器中直接执行推理。文中以仓库内置的 mnist-inference-web 示例为主线覆盖Flex与WebGpu两类后端的选型、wasm32-unknown-unknown目标编译、wasm-bindgen 桥接以及getrandom等依赖的 WASM 专项配置。读完本文你将掌握从 Rust 模型到浏览器可调用 JS API 的完整链路并能在自己的项目中复现这一流程。为什么 Burn 可以运行在浏览器中Burn 是一个不牺牲灵活性、效率与可移植性的下一代张量库与深度学习框架。与多数依赖特定系统库或原生运行时runtime的框架不同Burn 的推理路径被设计为可移植的只要后端Backend实现了张量运算模型代码就能在对应平台上运行浏览器也不例外。从仓库结构看这一设计贯穿于burn的核心 crate 中crates/burn/Cargo.toml 中flex、wgpu、webgpu等均为可选的 backend feature并注明所有依赖在关闭std时须支持no_std注释# ** Please make sure all dependencies support no_std when std is disabled **examples/mnist-inference-web/src/lib.rs 顶部声明#![cfg_attr(not(test), no_std)]证明推理组件在wasm32-unknown-unknown目标下可以做到无系统库运行。正是这种no_std能力使得 Burn 模型无需 WASI 等特殊系统库就能直接以wasm32-unknown-unknown目标编译并运行于任何现代浏览器中。两种可用的 WASM 后端Flex 与 WebGpu官方文档明确指出Burn 通过Flex和WebGpu两个后端支持 WebAssembly 执行。二者适用场景不同后端计算载体适用环境特点FlexCPU浏览器线程内所有浏览器纯软件实现兼容性最好no_std友好WebGpuGPU通过浏览器 WebGPU API支持 WebGPU 的现代浏览器利用 GPU 加速需要异步初始化Flex对应 feature 为flex即 crates/burn/Cargo.toml 中的flex [burn-core/flex, ...]。它是 CPU 上的纯 Rust 实现构建为 WASM 后无需任何外部系统库是示例的默认后端examples/mnist-inference-web/Cargo.toml 中default [flex]。WebGpu对应 feature 为wgpu。从 crates/burn/Cargo.toml 可以看到webgpu [wgpu, burn-core/webgpu, ...]、wgpu [burn-core/wgpu, ...]底层经由wgpucrate 对接浏览器的 WebGPU 接口可在支持 WebGPU 的浏览器中调用 GPU 计算。注意WebGpu 后端只适用于支持 WebGPU 的浏览器且设备初始化是异步的。后端选择如何影响代码两种后端的差异不仅体现在构建参数上也体现在运行时初始化方式上。以 examples/mnist-inference-web/src/state.rs 为例pub async fn build_and_load_model() - Model { #[cfg(all(feature flex, not(feature wgpu)))] let device Device::flex(); #[cfg(feature wgpu)] // Calls init_setup_async let device Device::wgpu_async(Default::default()).await; let model Model::new(device); let record ModuleRecord::from_bytes(Bytes::from_bytes_vec(STATE_ENCODED.to_vec())) .expect(Failed to decode state); model.load_record(record) }flex后端下Device::flex()是同步操作直接获得设备句柄wgpu后端下必须调用Device::wgpu_async(Default::default()).await异步等待 WebGPU 设备初始化完成。正因如此build_and_load_model被声明为async调用它的inference方法也是异步的见 examples/mnist-inference-web/src/web.rs。如果你的目标是最大兼容性直接使用默认的flex即可若追求 GPU 加速且目标浏览器明确支持 WebGPU则选择wgpu。依赖的专项配置getrandom 与 wasm-bindgen官方文档特别提醒面向 WebAssembly 时部分依赖需要额外配置尤其是使用WebGpu时getrandomcrate 必须显式设置。getrandom是 Rust 生态中提供操作系统随机数的底层 crate。在原生平台它默认通过系统调用获取随机数但在wasm32-unknown-unknown目标下没有操作系统可用因此必须在构建时显式指定随机数来源。这一配置可以通过环境变量RUSTFLAGS或.cargo/config.toml中的[target.wasm32-unknown-unknown]段完成例如为getrandom启用jsfeature基于浏览器crypto接口。仓库中的 build-for-web.sh 展示了通过RUSTFLAGS注入编译期配置的通用模式如--cfg web_sys_unstable_apisgetrandom的显式配置同样需要在编译阶段以类似方式生效。除getrandom外WASM 构建还依赖两类关键依赖见 examples/mnist-inference-web/Cargo.toml[dependencies] burn { workspace true, features [extension]} serde { workspace true } console_error_panic_hook { workspace true } # Wasm dependencies wasm-bindgen 0.2 js-sys 0.3wasm-bindgen生成 Rust 与 JavaScript 之间的桥接代码负责将 Rust 结构体、方法暴露为 JS 可调用的对象js-sys提供对浏览器内置 JS 对象如Array的绑定console_error_panic_hook将 Rust 的 panic 信息输出到浏览器控制台便于调试。此外该 crate 还设置了[lib] crate-type [cdylib]这是 wasm-pack 构建可被 JS 加载的 WASM 库所必需的库类型。实操从 Rust 模型到浏览器可调用 API仓库中的 mnist-inference-web 是官方文档点名的完整参考实现下面按步骤拆解。1. 模型与权重的组织模型定义在 examples/mnist-inference-web/src/model.rs是一个针对 28×28 灰度图像的卷积分类网络Conv2d BatchNorm MaxPool Linear输出 10 类概率预训练权重以 burnpack 格式静态嵌入examples/mnist-inference-web/src/state.rs 中static STATE_ENCODED: [u8] include_bytes!(../model.bpk);直接把 model.bpk 编译进 WASM 二进制省去运行时网络下载权重加载通过ModuleRecord::from_bytesmodel.load_record(record)完成而 state.rs 中的测试验证了嵌入权重与模型架构的匹配性。2. 用 wasm-bindgen 暴露 JS APIexamples/mnist-inference-web/src/web.rs 中Mnist结构体被#[wasm_bindgen]标注后导出给 JavaScript#[cfg_attr(target_family wasm, wasm_bindgen)] pub struct Mnist { model: OptionModel, } #[cfg_attr(target_family wasm, wasm_bindgen)] impl Mnist { #[cfg_attr(target_family wasm, wasm_bindgen(constructor))] pub fn new() - Self { ... } pub async fn inference(mut self, input: [f32]) - ResultArray, String { if self.model.is_none() { self.model Some(build_and_load_model().await); } let model self.model.as_ref().unwrap(); let device Default::default(); let input Tensor::1::from_floats(input, device).reshape([1, 28, 28]); let input ((input / 255) - 0.1307) / 0.3081; let output: Tensor2 model.forward(input); let output burn::tensor::activation::softmax(output, 1); let output output.into_data_async().await.unwrap(); let array Array::new(); for value in output.iter::f32() { array.push(value.into()); } Ok(array) } }关键点#[wasm_bindgen(constructor)]让 JS 端可以用new Mnist()创建实例inference接收一维f32切片28×28 灰度像素内部完成 reshape、归一化均值为 0.1307、标准差为 0.3081源自 PyTorch MNIST 示例、前向传播、softmax最后通过into_data_async().await将结果取回并转换为 JSArray模型采用惰性加载首次调用inference时才加载权重避免页面初始化卡顿。3. 构建为 WASM仓库提供了自动化脚本 build-for-web.shrustup target add wasm32-unknown-unknown cargo install wasm-pack # 若未安装 RUSTFLAGS-C embed-bitcodeyes -C codegen-units1 -C opt-level3 --cfg web_sys_unstable_apis wasm-pack build --out-dir pkg --release --target web --no-typescript --no-default-features --features $1其中$1传入flex或wgpu。--no-default-features配合--features精确控制后端--target web生成适用于浏览器 ES module 的包装代码产物输出到pkg目录。4. 前端页面与本地服务器examples/mnist-inference-web/index.html 提供一个手写数字画布基于 fabric.js配合 examples/mnist-inference-web/index.js 完成自动裁剪、缩放为 28×28、RGBA 转灰度然后调用 WASM 导出的接口import { default as wasm, Mnist } from ./pkg/mnist_inference_web.js; wasm().then((module) { const mnist new Mnist(); // 每次绘制结束后调用 mnist.inference(data)并用 Chart.js 绘制概率柱状图 });运行方式见 README./build-for-web.sh flex或wgpu需浏览器支持 WebGPU./run-server.sh启动本地 HTTP 服务默认端口 8000浏览器打开http://localhost:8000/。为什么要用本地服务器run-server.sh 的注释说明直接双击打开index.html会因浏览器安全限制CORS导致file://协议下无法加载pkg目录中的脚本必须通过 HTTP 服务提供。从仓库源码看 WASM 编译的底层保障no_std 与目标无关的推理路径示例 crate 根文件 examples/mnist-inference-web/src/lib.rs 只有三行模块声明加#![cfg_attr(not(test), no_std)]与extern crate alloc;。这意味着 Burn 的推理代码在no_std环境下仅依赖alloc堆分配这正是其能在wasm32-unknown-unknown目标下构建的前提。对比其他常见方案TensorFlow.js、ONNX Runtime JS 等需要在浏览器中携带运行时解释器Burn 的做法是把 Rust 编译器已优化过的模型代码直接编译进 WASM产物中只包含实际用到的计算例程。权重嵌入与加载校验state.rs中的单元测试 embedded_model_decodes_into_architecture 展示了 burnpack 权重加载的安全保证load_record会校验每个模型参数的存在性与形状若嵌入的.bpk与模型架构不一致会直接 panic从而避免在浏览器中运行损坏的模型。WebGpu 后端的异步初始化链选择wgpu后端时Device::wgpu_async(..).await触发的是一整条异步初始化链这也是为何build_and_load_model与inference都必须以async形式暴露给 JSwasm-bindgen会为async fn生成返回Promise的 JS 包装。这一点与flex后端的同步Device::flex()形成鲜明对比是后端切换时最容易踩的坑。常见问题排查现象可能原因处理方式浏览器控制台报 CORS / origin null直接以file://打开页面使用./run-server.sh或任意本地 HTTP 服务器编译失败getrandom相关错误wasm32-unknown-unknown下随机数来源未配置显式配置getrandom的 JS feature见上文“依赖的专项配置”wgpu后端运行时无 GPU 设备浏览器不支持 WebGPU改用flex后端或检查浏览器 WebGPU 开关权重加载 panicmodel.bpk与当前模型架构不匹配用mnist示例重新训练导出或按state.rs测试先行校验模型首次推理卡顿权重在首次inference时惰性加载可提前调用一次inference预热或改为页面加载时初始化总结在 Burn 中把深度学习模型搬到浏览器核心链路可以概括为三条后端选择flexCPU、兼容性最好、默认或WebGpuGPU、异步初始化、需浏览器支持依赖配置面向wasm32-unknown-unknown目标时显式配置getrandom并引入wasm-bindgen、js-sys等 WASM 依赖通过RUSTFLAGS注入必要的编译期配置构建与桥接以cdylib库类型 no_std源码为基础用 wasm-pack 构建产物借助#[wasm_bindgen]把模型推理封装为 JS 可调用的异步 API最终通过本地 HTTP 服务器在浏览器中运行。仓库中的 mnist-inference-web 是一个开箱即用的完整范例涵盖模型定义、权重嵌入、JS 桥接与前端交互全部环节remote-inference-web 则是同一思路的远程推理变体可进一步参考。按照本文的配置与步骤你可以把任意 Burn 训练好的模型快速部署到浏览器端实现零安装的交互式推理应用。【免费下载链接】burnBurn is a next generation tensor library and Deep Learning Framework that doesnt compromise on flexibility, efficiency and portability.项目地址: https://gitcode.com/GitHub_Trending/bu/burn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考