Expand description
This crate provides a safe idiomatic Rust binding to DLPack which is the standard in-memory, (mostly) hardware agnosnic data exchange interface and is recognized by major Deep Learning frameworks such as PyTorch, Tensorflow, MXNet, TVM and major array processing frameworks such as NumPy and CuPy. An important feature of this standard is to provide zero-cost tensor conversion across frameworks on a particular supported hardware.
The Minimum Supported Rust Version (MSRV) is the stable toolchain 1.57.0.
Usage
There are two usages related to where the owner of the underlying data / storage of a tensor resides. The main distinction is when the underlying data gets dropped and which framework is responsible for it.
Rust as the owner
In this case, ManagedTensor
is built from ManagedTensorProxy
which is the same proxy for ffi::DLManagedTensor
.
Non-Rust owner
In this case, either ffi::DLTensor
or its (invariant) Rust wrapper Tensor
can be used.
Example
For when ownership is not concerned, one can use Tensor
. Here is an example on how the conversion
can happen at zero-cost.
impl<'tensor> From<&'tensor mut ArrayD<f32>> for Tensor<'tensor> {
fn from(arr: &'tensor mut ArrayD<f32>) -> Self {
let inner = DLTensor::new(
arr.as_mut_ptr() as *mut c_void,
Device::default(),
arr.ndim() as i32,
DataType::f32(),
arr.shape().as_ptr() as *const _ as *mut i64,
arr.strides().as_ptr() as *const _ as *mut i64,
0,
);
Tensor(inner)
}
}
impl<'tensor> From<&'tensor mut Tensor<'tensor>> for ArrayD<f32> {
fn from(t: &'tensor mut Tensor<'tensor>) -> Self {
unsafe {
let arr = RawArrayViewMut::from_shape_ptr(t.0.shape().unwrap(), t.0.data() as *mut f32);
arr.deref_into_view_mut().into_dyn().to_owned()
}
}
}
And when ownership is concerned, one can use the ManagedTensor
. Here is an example on how the conversion
can happen at zero-cost.
impl<'tensor, 'ctx> From<&'tensor mut ArrayD<f32>> for ManagedTensor<'tensor, 'ctx> {
fn from(t: &'tensor mut ArrayD<f32>) -> Self {
let dlt: Tensor<'tensor> = Tensor::from(t);
let inner = DLManagedTensor::new(dlt.0, ptr::null_mut());
ManagedTensor(inner)
}
}
impl<'tensor, 'ctx> From<&mut ManagedTensor<'tensor, 'ctx>> for ArrayD<f32> {
fn from(mt: &mut ManagedTensor<'tensor, 'ctx>) -> Self {
let dlt: DLTensor = mt.0.inner.dl_tensor.into();
unsafe {
let arr = RawArrayViewMut::from_shape_ptr(dlt.shape().unwrap(), dlt.data() as *mut f32);
arr.deref_into_view_mut().into_dyn().to_owned()
}
}
}
See the complete examples/sample where the above cases have been simulated for the Rust ndarray conversion.
Re-exports
pub use datatype::DataType;
pub use datatype::DataTypeCode;
pub use device::Device;
pub use device::DeviceType;
pub use tensor::ManagedTensor;
pub use tensor::ManagedTensorProxy;
pub use tensor::Tensor;