use tch::{Cuda, Device, Tensor};
use crate::collator::Collator;
pub struct TorchPinnedCollator<C> {
inner: C,
pin_for: Option<Device>,
}
impl<C> TorchPinnedCollator<C> {
pub fn new(inner: C, enabled: bool) -> Self {
Self {
inner,
pin_for: enabled.then(accelerator).flatten(),
}
}
}
fn accelerator() -> Option<Device> {
if Cuda::is_available() {
Some(Device::Cuda(0))
} else if tch::utils::has_mps() {
Some(Device::Mps)
} else {
None
}
}
impl<Item, C> Collator<Item> for TorchPinnedCollator<C>
where
C: Collator<Item, Batch = Tensor>,
{
type Batch = Tensor;
fn collate(&self, items: Vec<Item>) -> crate::error::Result<Self::Batch> {
let batch = self.inner.collate(items)?;
match self.pin_for {
Some(device) => batch.f_pin_memory(device).map_err(Into::into),
None => Ok(batch),
}
}
}
#[cfg(test)]
mod tests {
use tch::{Device, Kind, Tensor};
#[test]
fn libtorch_rejects_pinning_for_the_cpu() {
let batch = Tensor::zeros([4], (Kind::Float, Device::Cpu));
assert!(batch.f_pin_memory(Device::Cpu).is_err());
}
}