Tensor Messages
Zero-copy tensor sharing between nodes for ML/AI workloads.
Tensor
A lightweight descriptor pointing to data in shared memory:
use horus::prelude::*; // Provides Tensor, TensorDtype, Device from horus_types
// Send tensor descriptor through Topic
let topic: Topic<Tensor> = Topic::new("camera.frames")?;
if let Some(tensor) = topic.recv() {
println!("Shape: {:?}", tensor.shape());
println!("Dtype: {:?}", tensor.dtype);
println!("Device: {}", tensor.device());
}
All tensor types are available via use horus::prelude::*.
TensorDtype
| Dtype | Size | Use Case |
|---|---|---|
| F32 | 4 | ML training/inference |
| F64 | 8 | High-precision computation |
| F16 | 2 | Memory-efficient inference |
| BF16 | 2 | Training on modern GPUs |
| U8 | 1 | Images |
| U16 | 2 | Depth sensors (mm) |
| U32 | 4 | Large indices |
| U64 | 8 | Counters, timestamps |
| I8 | 1 | Quantized inference |
| I16 | 2 | Audio, sensor data |
| I32 | 4 | General integer |
| I64 | 8 | Large signed values |
| Bool | 1 | Masks |
Helper methods:
let dtype = TensorDtype::F32;
assert_eq!(dtype.element_size(), 4);
assert!(dtype.is_float());
assert!(!dtype.is_signed_int());
println!("{}", dtype); // "f32"
// DLPack interop
let dl = dtype.to_dlpack();
let back = TensorDtype::from_dlpack(dl.0, dl.1).unwrap();
// Parse from string
let parsed = TensorDtype::parse("float32").unwrap();
Device
The Device struct is a Pod-safe repr(C) descriptor that tags tensors with a target device. Device::cuda(N) creates a descriptor — actual GPU tensor pools are not yet implemented.
Device::cpu() // CPU / shared memory
Device::cuda(0) // CUDA device descriptor (metadata only)
// Parse from string
let cpu = Device::parse("cpu").unwrap();
let dev = Device::parse("cuda:0").unwrap();
// Check device type
assert!(Device::cpu().is_cpu());
assert!(Device::cuda(0).is_cuda());
Auto-Managed Tensor Pools
Topic<Tensor> automatically manages a shared-memory TensorPool per topic. Users call alloc_tensor(), send_handle(), and recv_handle() instead of managing pools manually:
use horus::prelude::*;
let topic: Topic<Tensor> = Topic::new("camera.rgb")?;
// Allocate a 1080p RGB image from the topic's auto-managed pool
let handle = topic.alloc_tensor(&[1080, 1920, 3], TensorDtype::U8, Device::cpu())?;
// Write pixel data
let pixels = handle.data_slice_mut()?;
// ... fill pixels ...
// Send — only the descriptor is transmitted, not the tensor data.
// The actual tensor data stays in shared memory — true zero-copy.
topic.send_handle(&handle);
On the receiver side:
let topic: Topic<Tensor> = Topic::new("camera.rgb")?;
if let Some(recv_handle) = topic.recv_handle() {
let data = recv_handle.data_slice()?; // Zero-copy access to shared memory
println!("Shape: {:?}", recv_handle.shape());
println!("Dtype: {:?}", recv_handle.dtype());
}
// TensorHandle is RAII — refcount decremented automatically on drop
The pool is created lazily on first use and shared across all Topic<Tensor> instances with the same name — even across processes. Pool IDs are derived deterministically from the topic name.
With Manual TensorPool
For advanced use cases, you can manage pools directly:
use horus::prelude::*;
let pool = TensorPool::new(1, TensorPoolConfig::default())?;
let handle = TensorHandle::alloc(
Arc::new(pool),
&[1080, 1920, 3],
TensorDtype::U8,
Device::cpu(),
)?;
// Write data
handle.data_slice_mut()?[0] = 255;
// Share via Topic
topic.send(*handle.tensor());
Domain Types
For common robotics data, use the high-level domain types Image, PointCloud, and DepthImage which provide rich APIs (pixel access, point extraction, depth queries) while using the same zero-copy shared memory transport internally. See Message Types for their full API.
Python Interop
import horus
import numpy as np
# TensorPool and TensorHandle are available from the native module
pool = horus.TensorPool(pool_id=1, size_mb=1024, max_slots=1024)
handle = pool.alloc(shape=(1080, 1920, 3), dtype="uint8")
See Also
- TensorPool API — Pool management and configuration
- Message Types — All HORUS message types
- Python Memory Types — Image, PointCloud, DepthImage, TensorHandle with NumPy/PyTorch/JAX interop