This crate provides a safe idiomatic Rust binding to DLPack which is the standard in-memory, (mostly) hardware agnostic data format , 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.
There are two main cases related to where the owner of the underlying data / storage of a tensor resides and what kind of operations are to be done.
In this case, ManagedTensor
is built from ManagedTensorProxy
which is a safe proxy for the unsafe ffi::DLManagedTensor
.
In this case, the (invariant) Rust wrapper Tensor
can be used or if needed the unsafe ffi::DLTensor
.
When ownership is concerned, one can use the ManagedTensor
. Here is an example on how the bi-directional conversion
is done at zero-cost.
impl<'tensor, C> From<&'tensor mut ArrayD<f32>> for ManagedContext<'tensor, C> {
fn from(t: &'tensor mut ArrayD<f32>) -> Self {
let dlt: Tensor<'tensor> = Tensor::from(t);
let inner = DLManagedTensor::new(dlt.0, None);
ManagedContext(inner)
}
}
impl<'tensor, C> From<&mut ManagedContext<'tensor, C>> for ArrayD<f32> {
fn from(mt: &mut ManagedContext<'tensor, C>) -> 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()
}
}
}
And when ownership is not concerned, one can use Tensor
as a view. Here is an example on how the bi-directional converion
is done 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()
}
}
}
See the complete examples/sample where the above cases have been simulated for the Rust ndarray conversion.
Licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.