github tracel-ai/burn v0.22.0

latest release: v0.22.0-book
3 hours ago

Summary

Burn 0.22.0 brings five months of improvements to training and inference, along with our biggest API update yet. Over the last four years, we've kept APIs stable where possible while collecting your feedback on what could be improved. This release brings Burn's API much closer to what we want for 1.0.

The biggest change is that models and tensors no longer carry a backend generic. Devices select where and how they run, and editing a model requires much less recompilation. The release also adds LoRA and QLoRA support, parameter groups and multiple optimizers, graph capture, and improvements to remote execution. New tensor operations, optimizers, and kernel improvements round out the release.

For more details, check out the release post on our website.

No More B: Backend

Burn is still built around the Backend trait, with composable support for autodiff, kernel fusion, and remote execution. User code now selects these capabilities through Device, while models are plain types:

use burn::{
    module::Module,
    nn::{Linear, LinearConfig},
    tensor::Device,
};

#[derive(Module, Debug)]
pub struct Model {
    linear: Linear,
}

// Requires the cuda feature. Other options include Device::wgpu(..) and Device::flex().
let device = Device::cuda(0);
let model = Model {
    linear: LinearConfig::new(4, 2).init(&device),
};

More of the infrastructure is now implemented in Rust: Pliron replaces the MLIR-based intermediate representation, and Turso replaces the bundled SQLite dependency. CubeCL also adds LLVM-based CUDA and AMD GPU compilation paths. These changes reduce reliance on bundled C and C++ components and make more of the stack accessible to Rust contributors, though LLVM remains a native dependency for the backends that use it. Clean builds can take longer even as model-edit rebuilds become much faster.

Changelog

Breaking changes and migration

See Migrating to Burn 0.22 in the Burn Book for the complete migration guide, including before-and-after examples for devices, autodiff, modules, training, datasets, tensor operations, and custom integrations.

Start by removing backend parameters such as Model<B> and Tensor<B, D>, selecting a Device, and enabling autodiff with device.autodiff() before initializing a training model and its inputs. Candle has been removed in this release, and NdArray and LibTorch are being deprecated.

Records now use burnpack. Legacy MessagePack, binary, and JSON recorder files must be loaded with an older compatible Burn version and exported through burn-store before importing the weights into 0.22. Follow the checkpoint migration instructions; this transfers model parameters, not legacy optimizer or scheduler state.

What's Changed

Tensor & Modules

Training, Optimizers & Datasets

  • Add A-FINE image quality metric (#4894) @Capataina
  • Make RL event types mod public (#4951) @laggui
  • feat(metric): add BLEU score training metric (#4937) @kimjune01
  • feat(metric): add ROUGE-L score metric (#4967) @jaweed3
  • feat(metric)!: add multiclass and multi-label support to AUROC metric (#4960) @manucouto1
  • fix(train): guard TUI metric navigation against empty state (#4987) @SAY-5
  • feat(train): add training and evaluation progress logger and add them to the event processors (#4980) @Zatiji
  • fix(train): scroll TUI metric tabs to keep selected visible (#4995) @LucaCappelletti94
  • feat(train): add mouse support to TUI metric navigation (#4998) @LucaCappelletti94
  • refactor(rl): add inference device and update dqn example (#5009) @Charles23R
  • refactor(train)!: transform all Progress items into a global progress struct (#5012) @Zatiji
  • fix(train): use recv_timeout instead of try_recv. (#5021) @jeandudey
  • fix(dataset): fully qualify HuggingFace dataset repo ids (#5050) @ThierryCantin-Demers
  • fix: forward features flag in burn Cargo.toml for burn-vision (#5078) @Marc-AnthonyG
  • feat(metric): add AUC-PR (Average Precision) training metric (#4963) @manucouto1
  • fix(train): load checkpoint on the correct device (#5084) @laggui
  • fix(data): reuse persistent dataloader workers across epochs (#5073) @manucouto1
  • feat(train): add custom checkpointers (#5097) @Zatiji
  • Fix checkpointing + minor stuff (#5109) @Charles23R
  • fix metric logging when checkpoint + burn-train integration tests (#5116) @Charles23R
  • Feat/multi optimizers (#5121) @Charles23R
  • feat(dataset): make image extension matching case-insensitive (#5152) @veezhang
  • chore: change loop logic for data iterators and batchers (#5198) @Zatiji
  • fix(tui): silently unwind on training kill signal (#5223) @laggui
  • Feat/add get many in dataset trait (#5220) @Zatiji
  • feat: add sequential learning rate scheduler (#5204) @AnayGarodia
  • fix(optim)!: remove erroneous restart in CosineAnnealingLrScheduler (#5191) @DeathSurfing
  • fix(burn-train): correctly aggregate per-epoch metrics that require global statistics (#5218) @laggui
  • refactor(dataset)!: replace Vec<PixelDepth> with PixelData (#5271) @Charles23R
  • Change visibility of optimizer (#5314) @nathanielsimard
  • Keep metric items on their device instead of syncing them to the host (#5319) @nathanielsimard
  • fix(train): flush async metrics before checkpoint/early-stop (#5320) @TsaoLun
  • feat(vision): add color conversion and blurring transforms (#5339) @Charles23R
  • fix(vision): keep even filter2d output size (#5414) @Soundcreates
  • fix(optim): keep tensor data in optimizer records (#5407) @original4422
  • feat(optim): add LAMB optimizer (#5495) @Mikyx-1
  • fix(train): aggregate Dice statistics across batches (#5515) @Mikyx-1
  • fix(train): return final ROUGE-L value (#5517) @Mikyx-1
  • fix(rl): preserve deterministic mode in async batches (#5574) @Ultronen
  • fix(train): exclude padded samples from accuracy aggregation (#5578) @Mikyx-1
  • fix(optim): keep a parameter's checkpointing strategy across an update (#5618) @Marc-AnthonyG
  • refactor(dataset): back SqliteDataset with Turso instead of rusqlite (#5546) @antimora
  • fix(burn-dataset): cap MNIST item counts at the split size (#5667) @li-jin-quan
  • chore(deps): reduce dataframe dataset dependencies with polars-core (#5680) @laggui
  • fix(train): handle tied scores in average precision (#5684) @Mikyx-1
  • chore(deps): trim zip default features and fix burn-dataset nlp feature (#5715) @antimora
  • fix(train): flush partial gradient accumulation and step LR per optimizer update (#5729) @Mikyx-1
  • feat(optim): add Adafactor optimizer (#5775) @Mikyx-1
  • feat(optim): add Lion optimizer (#5741) @Mikyx-1
  • test(optim): strengthen optimizer save-load round-trip coverage (#5799) @laggui
  • fix: remove rl from default features (#5806) @antimora
  • feat(train): add labels to training progress loggers (#5805) @Charles23R
  • fix(optim): compute gradient norm clipping in F32 for half precision (#5843) @antimora
  • fix(tui): handle already-joined thread in manual close (#5866) @orbitwebsites-cloud
  • fix(train): compute AUROC with sorted score groups (#5900) @Mikyx-1
  • refactor(train)!: propagate execution errors through training and evaluation (#5896) @Charles23R
  • fix(train): validate top-k accuracy bounds (#5948) @Mikyx-1
  • fix(train): validate MS-SSIM configuration (#5950) @Mikyx-1

Backends & Performance

Distributed & Remote Execution

Model Storage & Import

  • fix(features): expose safetensors/pytorch support directly (#4985) @crutcher
  • fix: include RMS_NORM in normalization layer detection for safetensors adapter (#5023) @ogghead
  • fix(store): add .allow_partial(true) hint in TensorNotFound error w/ docs (#5032) @jaweed3
  • feat(store): extract burnpack format to burn-pack + add minimal record (#5064) @nathanielsimard
  • Refactor Record - Serialization & Deserialization of Module, Optimizer & LrScheduler (#5083) @nathanielsimard
  • feat(burn-store): add FloatCastAdapter for target-driven float dtype casting (#5164) @laurigates
  • fix(store): restore persisted ParamId on load_record and Applier apply (#5177) @jaweed3
  • fix(store): preserve module param id on load (#5180) @nathanielsimard
  • fix(burn-store): prevent CPU exhaustion via pickle memo bomb (#5120) @Infinty-ux
  • fix(burn-core): record params through their on_save mapper (#5208) @ThierryCantin-Demers
  • feat(pack): stream tensors on demand when writing burnpack files (#5349) @antimora
  • refactor(store)!: replace TensorSnapshot with burn_pack::Tensor (#5411) @antimora
  • fix(store): abort instead of double-dropping when a mapper unwinds (#5488) @antimora
  • fix(store): preserve extensionless burnpack paths (#5494) @rioyu123
  • fix(store): respect PyTorch tensor strides (#5392) @original4422
  • fix(store): exclude adapter-matched tensors from unused (#5536) @apoorvdarshan
  • fix(store): return deserialization error instead of panicking in nested Deserializer (#5496) @Sadik00789
  • fix(pack): validate size from aligned data offset (#5530) @Mikyx-1
  • fix(store): write safetensors files atomically (#5489) @antimora
  • fix(store): reject a loaded tensor whose dtype is the wrong kind (#5490) @antimora
  • fix(store): reject invalid path filter regex (#5558) @Mikyx-1
  • fix(pack): validate tensor byte lengths when reading (#5576) @Mikyx-1
  • fix(store): harden and restructure the PyTorch reader (#5593) @antimora
  • test(pack): check streaming memory with a drop hook, not a global allocator (#5666) @yuefdev
  • fix(store): collect PyTorch tensors nested in lists/tuples with indexed names (#5664) @SIDDARTHAREDDY8
  • refactor(store): extract the PyTorch reader into a burn-free pytorch-reader crate (#5656) @antimora
  • fix(pytorch-reader): report values load_config cannot represent instead of defaulting (#5728) @antimora
  • perf(pytorch-reader): read stored ZIP entries outside the archive lock (#5714) @antimora
  • fix(pytorch-reader): remove unsafe visitor cloning and deserialization panics (#5700) @Sadik00789
  • fix(pytorch-reader): open a checkpoint once and never reopen it by path (#5737) @antimora
  • fix(pytorch-reader): handle unsupported values in deserialize_any (#5764) @laggui
  • fix(burn-store): scope contiguous index mapping per prefix (#5750) @antimora
  • fix(pytorch-reader): thiserror source chains + reject non-checkpoint files (#5749) @superroket169
  • fix(pytorch-reader): accept checkpoints saved with compute_crc32=False (#5756) @antimora
  • feat(pytorch-reader): load torch.save(model) full-model pickles (#5766) @antimora
  • fix(store): enforce overwrite(false) at publish time, not just before the save (#5781) @antimora
  • feat(pack): make atomic writes the default (#5832) @antimora

Documentation & Examples

  • burn 0.21 cite (#4969) @Redhawk18
  • fix(doc): correct SgdConfig::init (#4986) @jaweed3
  • fix(docs): improve error messages with shape/dimension context (#4996) @jaweed3
  • fix(doc): inconsistent assertion for non-negative (#5016) @YichiZhang0613
  • fix(example): Device::enumerate configure (#5056) @laggui
  • chore(docs): update readme (#5080) @nathanielsimard @laggui
  • docs: document per-device default dtypes; make AlreadyInitialized error actionable (#5209) @laurigates
  • fix(examples): swapped lstm cell/hidden args (#5234) @ra1u
  • fix(examples): fix lstm bias backprop (#5235) @ra1u
  • fix(docs): correct LBFGSConfig::init doc comment (#5256) @Mikyx-1
  • docs(book): remove backend generics, update device, learner, module and add optimizer section (#5276) @laggui
  • fix(docs): correct tensor sort doc examples in orderable.rs (#5298) @4ktLuffy
  • fix(docs): correct chained reduction doc examples in numeric.rs (#5301) @4ktLuffy
  • docs(pack): clarify tensor thread-safety contract (#5500) @laggui
  • docs(tensor): fix unfold window formula (#5559) @Mikyx-1
  • docs(flex): fix stale statements in burn-flex docs and comments (#5619) @7487
  • docs(book): update backend extension guides and include maintained example sources (#5731) @laggui
  • docs(pytorch-reader): sync README with lib.rs (#5747) @superroket169
  • docs: fix typos and grammar in books and API comments (#5748) @hikmetba-bit
  • docs: clarify guidelines for minor documentation fixes (#5765) @laggui
  • docs: update guides and examples for Burn 0.22 (#5762) @laggui
  • docs: cover remaining 0.22 migration points and refresh stale pages (#5768) @antimora
  • docs: select the package when running examples from the repo root (#5773) @Liberxue
  • clarify 0.22 migration guidance and update API examples (#5800) @laggui
  • fix(examples): correctly format web inference probability labels (#5816) @laggui
  • fix(examples): correct WebGPU inference and keep live predictions responsive (#5823) @laggui
  • docs(book): document burn.toml runtime configuration (#5845) @laggui
  • docs: fix dead links in README and the Burn Book (#5863) @pratikgx
  • feat(examples): train and run MNIST on another machine's GPU with remote-mnist (#5906) @ThierryCantin-Demers
  • docs: fix license badge links in crate READMEs (#5923) @pratikgx
  • docs: update device selection table (#5937) @laggui
  • docs(book): sync the book with 0.22 API changes (#5954) @antimora
  • fix(examples): repair examples that no longer build or run (#5956) @antimora
  • docs: clarify burn-cpu vs burn-flex CPU backends (#5955) @antimora
  • docs(book): update ONNX import chapter for burn-onnx 0.22 (#5972) @antimora
  • docs: 0.22 release documentation pass (#5973) @antimora
  • docs: fix broken DeepWiki badge in README (#5966) @antimora
  • feat(example): bf16 training for ag-news text classification (#5984) @nathanielsimard
Maintenance & Dependencies
  • Bump version to 0.22.0-pre.1 (#4933) @laggui
  • fix(deps): update enumset to 1.1.13 (#4979) @laggui
  • Update CubeCL & CubeK (#4992) @louisfd
  • chore(cubek): update to interpolate refactor (#5003) @SamuelBelanger
  • fix(dep): update aes to 0.9.1 (yanked) (#5047) @laggui
  • fix(ci): use flex as default_backend and split jobs into backends, crates, and examples shards with merged lcov report (#5041) @laggui
  • fix(ci): remove fail_ci_if_error for code coverage (#5055) @laggui
  • chore(deps): bump actions/download-artifact from 7 to 8 (#5053) @dependabot[bot]
  • chore(deps): bump codecov/codecov-action from 6 to 7 (#5054) @dependabot[bot]
  • fix: fix inconsistent assertions (#5062) @YichiZhang0613
  • chore: bump MSRV from 1.92 to 1.95 (#5077) @laggui
  • chore(deps): update polars to 0.54 (#5072) @getong
  • update cube @louisfd
  • chore(deps): bump actions/checkout from 6 to 7 (#5093) @dependabot[bot]
  • fix(audit): update quinn-proto version in Cargo.lock (#5099) @laggui
  • chore(deps): update cube (#5098) @louisfd
  • update dependency versions in Cargo.lock (#5165) @SamuelBelanger
  • update cubek rev (#5169) @Charles23R
  • update cubecl (#5181) @Charles23R
  • chore(deps): bump actions/stale from 10 to 11 (#5247) @dependabot[bot]
  • chore: release 0.22.0-pre.1 (#5249) @laggui
  • fix: update publish deps (#5250) @laggui
  • Update revs (#5265) @nathanielsimard
  • update cube (#5275) @louisfd
  • chore: update cubek rev w/ matmul fixes (#5291) @laggui
  • update cube (#5299) @louisfd
  • fix(xtask): apply the webgpu feature on the wgpu CI runner (#5300) @4ktLuffy
  • chore(deps): update cubecl and cubek for BlockLevel::BlockTensor (unimplemented) (#5303) @ThierryCantin-Demers
  • update cubecl/cubek (#5315) @ThierryCantin-Demers
  • update cube (#5322) @louisfd
  • fix(deps): update cubecl and use correct windows crate versions (#5327) @laggui
  • fix: correct some copy-pasta mistakes (#5329) @laggui
  • chore: bump to version 0.22.0-pre.2 (#5338) @laggui
  • Bump cubecl and cubek revs for the pliron codegen fixes (#5355) @nathanielsimard
  • chore: simplify cargo run-checks local validation (#5356) @laggui
  • fix(deps): update h2 transitive dep (#5381) @laggui
  • Update cube (#5389) @louisfd
  • chore(ci): pin the shared actions to v11 (#5390) @ThierryCantin-Demers
  • chore(ci): pin the publish workflow to v11 (#5391) @ThierryCantin-Demers
  • chore: remove stale comment in root Cargo.toml (#5397) @ThierryCantin-Demers
  • chore: tracel github actions v11 (#5398) @syl20bnr
  • chore: fix clippy lints (#5401) @laggui
  • chore(deps): update cubecl + cubek (#5403) @ThierryCantin-Demers
  • chore: update to xtask v5 (#5404) @syl20bnr
  • Update/cube (#5420) @louisfd
  • chore: fix removed import (#5427) @laggui
  • Chore/bump cubecl cubek revs (#5497) @nathanielsimard
  • fix(deps): restore windows dependency compatibility in lockfile (#5499) @laggui
  • chore(deps): update cubecl + cubek to fix fma sigsev (#5501) @ThierryCantin-Demers
  • Update/cube (#5518) @louisfd
  • chore(deps): follow cubecl's collapsed memory throughput modes (#5510) @ThierryCantin-Demers
  • fix(no-std): use shared sync primitives across crates (#5543) @laggui
  • chore(deps): reduce unnecessary dependencies (#5544) @nathanielsimard
  • chore(deps): update cubecl and cubek for fallible throughput probes (#5561) @ThierryCantin-Demers
  • chore: update cubecl and cubek revs (#5586) @nathanielsimard
  • ci: reduce redundant compilation in macOS tests (#5669) @laggui
  • fix(deps): update rustls for cargo audit (#5672) @laggui
  • ci: reduce redundant compilation across test suites (#5671) @laggui
  • ci: reduce examples overhead by skipping coverage setup and enabling caching (#5681) @laggui
  • fix(deps): avoid enabling CubeCL through linalg defaults and respect vision defaults (#5694) @laggui
  • chore: update cubek (#5701) @louisfd
  • chore: update cubek (#5703) @Charles23R
  • fix(ci): publish burn-einsum and include it in no-std checks (#5727) @laggui
  • fix(deps): restore the windows crate versions the cube update changed (#5735) @ThierryCantin-Demers
  • chore: bump version to 0.22.0-pre.4 (#5776) @laggui
  • chore(deps): bump iroh to 1.2.0 (#5830) @ThierryCantin-Demers
  • chore(deps): drop unused bincode workspace dependency (#5831) @antimora
  • chore(deps): bump cubek to a066bdd (#5841) @louisfd
  • chore(deps): bump cubek to b40b522 (#5848) @louisfd
  • chore(deps): bump cubecl to a1bb768 and cubek to 9db95ba (#5854) @nathanielsimard
  • fix(deps): restore gpu-allocator's windows version to match wgpu-hal (#5867) @ax1s-x1zz
  • chore(deps): bump cubek to 7d60e30 (#5870) @louisfd
  • chore(deps): bump cubek to 41a4ab0 and cubecl to 33b6dfb (#5887) @louisfd
  • chore: bump cubecl to f0cf8383 and cubek to 9f35e2ab (#5895) @nathanielsimard
  • chore: bump cubek to 6927503 (#5905) @louisfd
  • update cube (#5907) @louisfd
  • chore: bump cubek to bb461fb (#5913) @louisfd
  • chore: bump cubek to 5753e85 (#5915) @louisfd
  • chore: bump cubecl to 48301b5 and cubek to 2e07d52 (#5917) @nathanielsimard
  • chore: bump cubek to e84f83d and cubecl to 48301b5 (#5918) @louisfd
  • chore: bump cubek to 08f8f96 (#5926) @louisfd
  • chore(lint): allow redundant_field_names pending upstream Clippy fix (#5927) @laggui
  • chore(lint): allow redundant_field_names pending upstream Clippy fix (#5928) @laggui
  • chore: bump cubek to cafd262 and cubecl to 3631455 (#5934) @louisfd
  • chore: bump cubek to 645ead8 (#5936) @louisfd
  • chore: bump cubek to fbed329 (#5940) @louisfd
  • chore: bump cubek to 3d53983 and cubecl to 202a9bc (#5943) @louisfd
  • chore: bump cubek to 94a2266 (#5946) @louisfd
  • chore: bump cubek to a8207f8 (#5957) @louisfd
  • fix(ci): let the scheduled valgrind and cargo-careful jobs install their tools (#5941) @glaziermag
  • chore: upgrade dependencies (#5958) @antimora
  • chore: update version to 0.22.0 (#5985) @laggui

Don't miss a new burn release

NewReleases is sending notifications on new releases.