use burn_core::Tensor;
use burn_core::module::ParamId;
use burn_core::tensor::Device;
use super::GradientsParams;
use alloc::vec::Vec;
#[derive(Default)]
pub struct MultiGradientsParams {
pub grads: Vec<(GradientsParams, Device)>,
}
impl MultiGradientsParams {
pub fn remove<const D: usize>(&mut self, id: ParamId) -> Option<(Tensor<D>, Device)> {
let (mut tensor, device, index) = self.select(id)?;
for (i, (grads, _)) in self.grads.iter_mut().enumerate() {
if i == index {
continue;
}
if let Some(grad) = grads.remove::<D>(id) {
tensor = tensor + grad.to_device(&device);
}
}
Some((tensor, device))
}
fn select<const D: usize>(&mut self, id: ParamId) -> Option<(Tensor<D>, Device, usize)> {
let id_val = id.val() as usize;
for i in 0..self.grads.len() {
let selected_device_index = (id_val + i) % self.grads.len();
if let Some(acc) = self.grads[selected_device_index].0.remove::<D>(id) {
let device = &self.grads[selected_device_index].1;
return Some((acc.to_device(device), device.clone(), selected_device_index));
}
}
None
}
}