Skip to main content

burn_tensor/tensor/api/
transaction.rs

1use super::Tensor;
2use crate::{ExecutionError, TensorData};
3use alloc::vec::Vec;
4use burn_backend::ops::TransactionPrimitive;
5use burn_dispatch::Dispatch;
6
7/// A transaction can [read](Self::register) multiple tensors at once with a single operation improving
8/// compute utilization with optimized laziness.
9///
10/// # Example
11///
12/// ```rust,ignore
13///  let [output_data, loss_data, targets_data] = Transaction::default()
14///    .register(output)
15///    .register(loss)
16///    .register(targets)
17///    .execute()
18///    .try_into()
19///    .expect("Correct amount of tensor data");
20/// ```
21pub struct Transaction {
22    opaque: transaction_opaque::Opaque,
23}
24
25burn_std::obfuscate!(
26    type: TransactionPrimitive<Dispatch>,
27    module: transaction_opaque,
28    derives: [Send, Sync],
29);
30
31impl Default for Transaction {
32    fn default() -> Self {
33        Self::from_op(TransactionPrimitive::<Dispatch>::default())
34    }
35}
36
37impl Transaction {
38    /// Crate-internal constructor wrapping a dispatch-level transaction.
39    pub(crate) fn from_op(op: TransactionPrimitive<Dispatch>) -> Self {
40        Self {
41            opaque: transaction_opaque::Opaque::new(op),
42        }
43    }
44
45    /// Crate-internal mutable borrow of the underlying transaction primitive.
46    pub(crate) fn as_op_mut(&mut self) -> &mut TransactionPrimitive<Dispatch> {
47        self.opaque.as_mut()
48    }
49
50    /// Crate-internal owning extraction of the underlying transaction primitive.
51    pub(crate) fn into_op(self) -> TransactionPrimitive<Dispatch> {
52        self.opaque.into_inner()
53    }
54
55    /// Add a [tensor](Tensor) to the transaction to be read.
56    pub fn register<const D: usize, K: crate::kind::Transaction>(
57        mut self,
58        tensor: Tensor<D, K>,
59    ) -> Self {
60        K::register_transaction(self.as_op_mut(), tensor.primitive);
61        self
62    }
63
64    /// Executes the transaction synchronously and returns the [data](TensorData) in the same order
65    /// in which they were [registered](Self::register).
66    pub fn execute(self) -> Vec<TensorData> {
67        burn_std::future::block_on(self.execute_async())
68            .expect("Error while reading data: use `try_execute` to handle error at runtime")
69    }
70
71    /// Executes the transaction synchronously and returns the [data](TensorData) in the same
72    /// order in which they were [registered](Self::register).
73    ///
74    /// # Returns
75    ///
76    /// Any error that might have occurred since the last time the device was synchronized.
77    pub fn try_execute(self) -> Result<Vec<TensorData>, ExecutionError> {
78        burn_std::future::block_on(self.execute_async())
79    }
80
81    /// Executes the transaction asynchronously and returns the [data](TensorData) in the same order
82    /// in which they were [registered](Self::register).
83    pub async fn execute_async(self) -> Result<Vec<TensorData>, ExecutionError> {
84        self.into_op().execute_async().await
85    }
86}