tracel-ai/burn · critical

Can't use deformable convolution backwards pass without atom

Error message

Can't use deformable convolution backwards pass without atomics

What it means

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.

Source

Thrown at crates/burn-ndarray/src/ops/deform_conv.rs:657

                let yp = f32::floor(y) + dy as f32;
                let xp = f32::floor(x) + dx as f32;

                if yp >= 0.0
                    && yp < height as f32
                    && xp >= 0.0
                    && xp < width as f32
                    && f32::abs(y - yp) < 1.0
                    && f32::abs(x - xp) < 1.0
                {
                    let weight = (1.0 - f32::abs(y - yp)) * (1.0 - f32::abs(x - xp));

                    #[cfg_attr(not(target_has_atomic = "32"), allow(unused))]
                    let value = mask_value * weight * col;

                    #[cfg(target_has_atomic = "32")]
                    grad_input[[yp as usize, xp as usize]].fetch_add(value, Ordering::AcqRel);
                    #[cfg(not(target_has_atomic = "32"))]
                    panic!("Can't use deformable convolution backwards pass without atomics");
                }
            }
        }
    }
}

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Build for a target with 32-bit atomics (standard x86_64/aarch64 platforms).
  2. Do training on a backend like burn-cubecl (GPU) or burn-tch instead of ndarray on the restricted target.
  3. Split inference and training so only supported targets run backward passes.
  4. If implementing, replace fetch_add with a mutex/serialized accumulation.

Example fix

// before
# Cargo.toml target: thumbv7m-none-eabi (no 32-bit atomics)
grads = loss.backward(); // panics in deform conv backward
// after
# Train on x86_64 or use burn-cubecl/tch backend for training
grads = loss.backward();
Defensive patterns

Strategy: fallback

Validate before calling

#[cfg(not(target_has_atomic = "32"))]
compile_error!("deform conv backward requires 32-bit atomics on this target");

Type guard

fn deform_backward_supported() -> bool { cfg!(target_has_atomic = "32") }

Try / catch

// Rust panics are not catchable; guard by target config
if !cfg!(target_has_atomic = "32") {
    // route training to another backend
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/ff59ea36599f46e5. Report an issue: GitHub.