pub struct Tensor {
pub name: String,
pub dtype: DType,
pub shape: Shape,
pub param_id: Option<u64>,
/* private fields */
}Expand description
A single tensor in a burnpack container, decoupled from any tensor library.
The bytes are in little-endian layout, and are reached with to_bytes,
into_bytes, or into_parts. Their length is
available up front via
byte_len whether or not they exist yet. For every dtype but
DType::QFloat that length is the element count implied by shape and
dtype; quantized data packs its values and appends scales inline, so it
is not a product of the two.
Construct one with new when the data is already in memory, or
deferred when it is not. A Reader produces resident
tensors, though for a file-backed source the bytes are still only read from disk on
access.
§Thread safety
On targets with pointer-width atomics, Tensor is Send + Sync whether its bytes are
resident or deferred. Accordingly, deferred requires its provider to
be Send + Sync on those targets. Without pointer-width atomics, deferred providers are
held in an Rc, so Tensor implements neither trait.
Fields§
§name: StringFully-qualified tensor name (e.g. "encoder.layer1.weight").
dtype: DTypeData type of the tensor.
shape: ShapeTensor shape.
param_id: Option<u64>Optional parameter id, used to preserve identities for stateful training.
Implementations§
Source§impl Tensor
impl Tensor
Sourcepub fn new(
name: String,
dtype: DType,
shape: impl Into<Shape>,
param_id: Option<u64>,
bytes: Bytes,
) -> Self
pub fn new( name: String, dtype: DType, shape: impl Into<Shape>, param_id: Option<u64>, bytes: Bytes, ) -> Self
Create a tensor from its metadata and raw bytes.
Sourcepub fn deferred(
name: String,
dtype: DType,
shape: impl Into<Shape>,
param_id: Option<u64>,
byte_len: usize,
provider: impl Fn() -> Result<Bytes, Error> + Send + Sync + 'static,
) -> Self
pub fn deferred( name: String, dtype: DType, shape: impl Into<Shape>, param_id: Option<u64>, byte_len: usize, provider: impl Fn() -> Result<Bytes, Error> + Send + Sync + 'static, ) -> Self
Create a tensor whose bytes are produced on demand.
byte_len must equal the length of the Bytes provider eventually returns, since
Writer reserves exactly that much space in the data section before
calling it. Getting it wrong would misplace every later tensor, so it is checked twice:
while planning, against shape and dtype, and while writing, against the bytes
actually produced. Quantized data is exempt from the first, its length being packed
values plus inline scales rather than a product of the two, so there the write-time
check is the only guard.
provider runs at most once per write, when the writer reaches this tensor, and its
result is dropped before the next tensor’s is requested. Producing the data there -
reading a parameter back from a device, say - is what bounds a save’s peak host memory
by the largest single tensor rather than by the whole model.
Sourcepub fn byte_len(&self) -> usize
pub fn byte_len(&self) -> usize
Number of raw bytes the tensor occupies, known without producing them.
Sourcepub fn to_bytes(&self) -> Result<Bytes, Error>
pub fn to_bytes(&self) -> Result<Bytes, Error>
The tensor’s raw little-endian bytes, leaving it intact.
Named to_ rather than bytes because it can cost the whole tensor: a Deferred one
re-runs its provider (nothing is cached), and a Resident one is deep-copied unless
its Bytes can share their backing. Prefer into_bytes, or
into_parts when the metadata is wanted too.
Sourcepub fn into_bytes(self) -> Result<Bytes, Error>
pub fn into_bytes(self) -> Result<Bytes, Error>
Sourcepub fn into_parts(
self,
) -> Result<(String, DType, Shape, Option<u64>, Bytes), Error>
pub fn into_parts( self, ) -> Result<(String, DType, Shape, Option<u64>, Bytes), Error>
Split into (name, dtype, shape, param_id, bytes), producing the bytes if deferred.
The fields are public, but taking the bytes consumes the tensor, so reading both otherwise means cloning the metadata first. This hands over everything in one move.