Rust in Everything
基于 burn 0.22.1

No execution backend is enabled

主线位置:算子主线的分岔点之前。Dispatch 要按设备选后端(Dispatch),可一个后端都没编进来,第一个需要设备的地方 DispatchDevice::default() 只能 panic;张量还没建出来,三条主线都没开始。

flowchart TB
  dep["burn 默认 feature"] --> none["没有任何后端"]
  none --> buildok["编译通过"]
  buildok --> defdev["Device::default"]
  defdev --> pnc["运行期 panic"]
  none --> ctor["Device::flex"]
  ctor --> e599["编译期 E0599"]
  fix["features 加 flex"] --> run["两种写法都能跑"]

本页实验 crate pa-nobackend(debug),依赖只写 burn = { version = "=0.22.1" },两个本地 feature 控制实验:flex_ctor 把 Device::default() 换成 Device::flex(),with_flex 打开 burn/flex。平台 M2 Max、macOS 27、rustc 1.99.0。

现象

use burn::tensor::{Device, Tensor};

fn main() {
  #[cfg(feature = "flex_ctor")]
  let device = Device::flex();
  #[cfg(not(feature = "flex_ctor"))]
  let device = Device::default();
  println!("device = {device:?}");
  let t = Tensor::<1>::from_floats([1.0, 2.0], &device);
  println!("{:?}", t.into_data().try_to_vec::<f32>());
}

cargo run:编译没有任何警告,运行就 panic,device = 那一行都没打印出来:

   Compiling pa-nobackend v0.1.0 (~/exp-burn/pa-nobackend)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.50s
     Running `~/exp-burn/target-pa/debug/pa-nobackend`

thread 'main' (3431562) panicked at ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/burn-dispatch-0.22.1/src/device.rs:381:9:
No execution backend is enabled. Enable a Burn backend feature such as `flex`, `wgpu`, or `cuda`. To record a graph without executing it, enable `capture` and use Device::capture().
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
exit=101

cargo run --features flex_ctor,同一个原因变成编译错误,而且 rustc 的提示把人往 Device::new 引:

   Compiling pa-nobackend v0.1.0 (~/exp-burn/pa-nobackend)
error[E0599]: no associated function or constant named `flex` found for struct `burn::tensor::Device` in the current scope
   --> src/main.rs:5:24
    |
  5 |   let device = Device::flex();
    |                        ^^^^ associated function or constant not found in `burn::tensor::Device`
    |
note: if you're trying to build a new `burn::tensor::Device`, consider using `burn::tensor::Device::new` which returns `burn::tensor::Device`
   --> ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/burn-tensor-0.22.1/src/device.rs:165:5
    |
165 |     pub fn new(device: impl Into<DispatchDevice>) -> Self {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0599`.
error: could not compile `pa-nobackend` (bin "pa-nobackend") due to 1 previous error
exit=101

Device::new 要一个 DispatchDevice,没有后端时那个枚举里没有能构造的变体,照这个提示改走不通。

出处

burn 的默认 feature 是 std 和 optim(连带 autodiff),没有执行后端,crates/burn/src/lib.rs 写明了「no execution backend」。feature 表见怎么读这一卷。

两种报错来自两个层次:

  • Device::flex()、Device::metal(..) 这些构造函数各自带 #[cfg(feature = ...)](Device::flex),没开 feature 时函数不存在,所以是 E0599。
  • Device::default() 始终存在。DispatchDevice::default 按 CUDA、Metal、……、Flex、Remote、NdArray 的顺序找第一个开着的后端,一个都没有就走到函数末尾那句 panic!(device.rs:381)。顺序和 BURN_DEVICE 的覆盖见 Device。

为什么没有后端还能编译:burn-dispatch 的构建脚本在没有后端时不发 backend_enabled cfg,DispatchTensor 等枚举里只剩一个包着 Infallible 的 NoBackend 占位(Dispatch 的「NoBackend:一个后端都没开」)。这样一个只写模型、不挑后端的库可以只依赖 burn 的 API,把选择留给最终的应用;代价就是应用忘了选时,错误要到运行期才出现。0.22.0 之前没开后端时会悄悄编进 Flex,那段来历在 Dispatch 页的冷知识里。

修法

在依赖里选一个后端。CPU 用 flex(纯 Rust),Apple 芯片的 GPU 用 metal,其余见 feature 表:

[dependencies]
burn = { version = "=0.22.1", features = ["flex"] }

pa-nobackend 用 --features with_flex(即 burn/flex)重跑,Device::default() 那一版:

    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.70s
     Running `~/exp-burn/target-pa/debug/pa-nobackend`
device = Device<Flex(Cpu)>
Ok([1.0, 2.0])
exit=0

--features with_flex,flex_ctor(Device::flex() 那一版)输出相同的两行,exit=0。

只开了 flex 时 Device::default() 就是 Flex。开了多个后端时默认值按上面的顺序挑,GPU 排在 CPU 前面;想固定设备,在代码里写 Device::flex() / Device::metal(..),或者设 BURN_DEVICE。

写库的话反过来:库的 Cargo.toml 不开后端,函数接收 &Device 参数,不在库里调 Device::default();由应用的 Cargo.toml 选后端。cargo 会把整个构建的 feature 合并,应用开了 flex,库里的 burn 也就有了 Flex。

怎么确认没中招

  • cargo tree -e features -i burn-dispatch 里要能看到至少一个后端 feature(flex、metal、wgpu、cuda 等)。pa-nobackend 不带 feature 时,burn-dispatch 打开的 feature 只有这几个:

    ├── burn-dispatch feature "autodiff"
    ├── burn-dispatch feature "burn-autodiff"
    │   └── burn-dispatch feature "autodiff" (*)
    ├── burn-dispatch feature "default"
    └── burn-dispatch feature "std"
        ...
    

    加上 --features with_flex 后多出一行 ├── burn-dispatch feature "flex"。

  • 程序启动时打印一次 Device::default() 或你实际用的设备:Device<Flex(Cpu)>、Device<Cube(Wgpu(...))> 都说明后端在。

  • 看到 E0599「no associated function ... named flex」,不要按提示去用 Device::new,去 Cargo.toml 加 feature。

小结

  • burn 的默认 feature 没有执行后端:能编译,Device::default() 在运行期 panic「No execution backend is enabled」。
  • 按后端命名的构造函数随 feature 出现,没开就是编译期 E0599,rustc 指向的 Device::new 帮不上忙。
  • 修法是在 features 里选一个后端;库不选,应用选。

💬 关联讨论

发起讨论
加载中...