1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
//! ## REQ status (per `.design/ferrotorch-core/device.md`)
//!
//! Tensor location enum mirroring `c10::Device` (`c10/core/Device.h:31`).
//!
//! | REQ | Status | Evidence |
//! |---|---|---|
//! | REQ-1 (Cpu variant) | SHIPPED | variant `Device::Cpu` at `device.rs:15` with `#[default]`; consumer `storage.rs` `TensorStorage::cpu(...).device() == Device::Cpu`; also `bool_tensor.rs:152` returns `Cpu` for any `TensorStorage::cpu`-backed `BoolTensor` |
//! | REQ-2 (Cuda variant) | SHIPPED | variant `Device::Cuda(usize)` at `device.rs:18`; consumer `int_tensor.rs:268-323` `IntTensor::to` matches `(Cpu, Cuda(_))` / `(Cuda(_), Cpu)` arms for H2D / D2H transfer |
//! | REQ-3 (Xpu variant) | SHIPPED | variant `Device::Xpu(usize)` at `device.rs:22`; consumer `error.rs:259` `FerrotorchError::DeviceMismatch { expected, got }` carries Xpu values; `int_tensor.rs:336` rejects `Xpu` destination via structured error |
//! | REQ-4 (Mps variant) | SHIPPED | variant `Device::Mps(usize)` at `device.rs:26`; consumer `bool_tensor.rs:261-266` `(from, to) => Err(InvalidArgument)` arm pattern-matches on `Mps(_)` |
//! | REQ-5 (Meta variant) | SHIPPED | variant `Device::Meta` at `device.rs:31`; consumer `storage.rs` `TensorStorage::Meta` arm — `try_as_slice` returns `GpuTensorNotAccessible` for Meta variant |
//! | REQ-6 (predicates) | SHIPPED | `is_cpu` / `is_cuda` / `is_xpu` / `is_mps` / `is_meta` at `device.rs:36-64`; consumer `bool_tensor.rs:158`, `int_tensor.rs:205`, every `if a.device().is_cuda()` branch across `grad_fns/*.rs` |
//! | REQ-7 (Display) | SHIPPED | `Display` impl at `device.rs:66-76` matching `c10::Device::str()` (`c10/core/Device.h:167`); consumer `error.rs:11` `#[error("device mismatch: expected {expected}, got {got}")]` |
//! | REQ-8 (Copy/Hash derives) | SHIPPED | `#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]` at `device.rs:12`; consumer `gpu_dispatch.rs` registry + `Tensor<T>::device() == other.device()` PartialEq compares in `bool_tensor.rs:333`, `int_tensor.rs:436` |
/// Device on which a tensor's data resides.
///
/// `Meta` is a special device that does not allocate any backing memory:
/// meta tensors carry shape, dtype, and device information but no data.
/// They are useful for shape inference, dry-run model construction, and
/// inspecting parameter counts of huge models without actually allocating
/// the weights. Mirrors `torch.device("meta")`.
///
/// `Xpu` mirrors PyTorch's `torch.device("xpu")` and addresses Intel
/// GPUs (Arc series, Data Center GPU Max) via the portable CubeCL
/// wgpu runtime that the `ferrotorch-xpu` crate wraps. CL-452.