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里选一个后端;库不选,应用选。