{"record":{"id":"bbf6e68548591b62","repo":"tracel-ai/burn","slug":"both-tensors-should-be-on-the-same-device","errorCode":null,"errorMessage":"Both tensors should be on the same device {:?} != {:?}","messagePattern":"Both tensors should be on the same device (.+?) != (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/burn-cubecl/src/tensor/base.rs","lineNumber":306,"sourceCode":"\n        impl NumericUnaryOpFamily for Copy {\n            type Options = ();\n            type Unary<T: Numeric, N: Size> = Self;\n        }\n\n        let tensor = self.clone();\n        launch_unary_numeric::<Copy, _>(tensor, |_| ())\n    }\n\n    /// Check if the tensor is safe to mutate.\n    pub fn can_mut(&self) -> bool {\n        self.handle.can_mut()\n    }\n\n    /// Assert that both tensors are on the same device.\n    pub fn assert_is_on_same_device(&self, other: &Self) {\n        if self.device != other.device {\n            panic!(\n                \"Both tensors should be on the same device {:?} != {:?}\",\n                self.device, other.device\n            );\n        }\n    }\n\n    /// Check if the current tensor is contiguous.\n    ///\n    /// A tensor is contiguous if the elements are stored in memory\n    /// if the strides in non-increasing order and the\n    /// strides at position k is equal to the product of the shapes\n    /// at all positions greater than k. However, all axes with a shape of 1 are ignored.\n    pub fn is_contiguous(&self) -> bool {\n        is_contiguous(self.meta.shape(), self.meta.strides())\n    }\n\n    /// Check if the current tensor has a contiguous backing buffer (no overlap and no empty memory\n    /// regions within the shape).","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-cubecl/src/tensor/base.rs#L288-L324","documentation":"burn-cubecl panics when two tensors involved in the same operation live on different devices (e.g. one on GPU 0, another on GPU 1, or one on CPU and one on GPU). `assert_is_on_same_device` compares the `device` field of both CubeTensor handles before an operation proceeds, since most kernels cannot read inputs across devices. This is a deliberate fail-fast instead of an implicit (and slow or impossible) cross-device copy.","triggerScenarios":"Any binary or multi-tensor operation (e.g. element-wise ops, matmul, cat, comparison ops) built on CubeTensor where the two inputs were created on, moved to, or lazily computed on different devices: `t1 = Tensor::<Backend, 2>::from_data(data1, &device_g0)` combined with `t2` on device_g1 or on the CPU device.","commonSituations":"Multi-GPU setups where weights were initialized on GPU 0 but inputs were sent to GPU 1; mixing CPU-created tensors with GPU tensors; loading a checkpoint/model saved with a CPU device record and running it against a GPU device; wrapping tensors in a struct created once with an old device reference.","solutions":["Call `.to_device(&device)` on one of the tensors to bring both onto the same device before the operation.","Standardize on a single `device` variable (e.g. from `B::Device::default()`) and use it for every tensor creation, model `.to_device()`, and data load.","If using multi-GPU, explicitly place both operands on the device of the current process/rank (see burn distributed / DDP patterns).","Check that model parameters were moved with `model.to_device(&device)` after loading, not just the input data."],"exampleFix":"// before\nlet model = Model::new(&device_a).to_device(&device_a);\nlet input = Tensor::from_data(data, &device_b);\nlet out = model.forward(input); // panics: device_a != device_b\n\n// after\nlet input = Tensor::from_data(data, &device_a); // same device as model\nlet out = model.forward(input);","handlingStrategy":"validation","validationCode":"// before the op\nassert_eq!(t1.device(), t2.device(), \"tensors on different devices: {:?} vs {:?}\", t1.device(), t2.device());","typeGuard":"// Rust has no runtime type guard; use an explicit check helper\nfn same_device<D: burn::tensor::DeviceOps>(a: &D, b: &D) -> bool { a == b }","tryCatchPattern":"// panic-based; cannot be caught — align devices instead\nlet t2 = t2.to_device(&t1.device());","preventionTips":["Keep one canonical `device` value and thread it through tensor creation, model init, and data loading","Always `.to_device(&device)` models and inputs after loading from disk/checkpoints","In multi-GPU code, derive the device from the current rank/process context, never hardcode","Enable assertions in debug builds to catch mismatches early during development"],"tags":["gpu","device-mismatch","burn","rust"],"backgroundTag":"tensor-device-mismatch","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"}