{"record":{"id":"ff59ea36599f46e5","repo":"tracel-ai/burn","slug":"can-t-use-deformable-convolution-backwards-pass-wi","errorCode":null,"errorMessage":"Can't use deformable convolution backwards pass without atomics","messagePattern":"Can't use deformable convolution backwards pass without atomics","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/burn-ndarray/src/ops/deform_conv.rs","lineNumber":657,"sourceCode":"                let yp = f32::floor(y) + dy as f32;\n                let xp = f32::floor(x) + dx as f32;\n\n                if yp >= 0.0\n                    && yp < height as f32\n                    && xp >= 0.0\n                    && xp < width as f32\n                    && f32::abs(y - yp) < 1.0\n                    && f32::abs(x - xp) < 1.0\n                {\n                    let weight = (1.0 - f32::abs(y - yp)) * (1.0 - f32::abs(x - xp));\n\n                    #[cfg_attr(not(target_has_atomic = \"32\"), allow(unused))]\n                    let value = mask_value * weight * col;\n\n                    #[cfg(target_has_atomic = \"32\")]\n                    grad_input[[yp as usize, xp as usize]].fetch_add(value, Ordering::AcqRel);\n                    #[cfg(not(target_has_atomic = \"32\"))]\n                    panic!(\"Can't use deformable convolution backwards pass without atomics\");\n                }\n            }\n        }\n    }\n}\n","sourceCodeStart":639,"sourceCodeEnd":663,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-ndarray/src/ops/deform_conv.rs#L639-L663","documentation":"The deformable convolution backward pass accumulates input gradients in place using 32-bit atomics (fetch_add). On targets without 32-bit atomics the kernel cannot safely accumulate concurrent writes, so it panics rather than producing a race-corrupted gradient.","triggerScenarios":"Running backward() through a deform conv layer on a platform where target_has_atomic = \"32\" is not set (e.g. certain embedded/no-std or unusual CPU targets).","commonSituations":"Training (not inference) on embedded or exotic targets without atomic 32-bit support; cross-compiling for a target lacking atomics; using deform conv backward on wasm/embedded builds.","solutions":["Build for a target with 32-bit atomics (standard x86_64/aarch64 platforms).","Do training on a backend like burn-cubecl (GPU) or burn-tch instead of ndarray on the restricted target.","Split inference and training so only supported targets run backward passes.","If implementing, replace fetch_add with a mutex/serialized accumulation."],"exampleFix":"// before\n# Cargo.toml target: thumbv7m-none-eabi (no 32-bit atomics)\ngrads = loss.backward(); // panics in deform conv backward\n// after\n# Train on x86_64 or use burn-cubecl/tch backend for training\ngrads = loss.backward();","handlingStrategy":"fallback","validationCode":"#[cfg(not(target_has_atomic = \"32\"))]\ncompile_error!(\"deform conv backward requires 32-bit atomics on this target\");","typeGuard":"fn deform_backward_supported() -> bool { cfg!(target_has_atomic = \"32\") }","tryCatchPattern":"// Rust panics are not catchable; guard by target config\nif !cfg!(target_has_atomic = \"32\") {\n    // route training to another backend\n}","preventionTips":["Train only on targets with 32-bit atomics","Use burn-cubecl or burn-tch for training on restricted platforms","Run backward passes on desktop/GPU targets; keep embedded to inference"],"tags":["rust","burn","atomics","embedded","backward-pass"],"backgroundTag":"missing-atomic-support","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}