use crate::local::tensor_map::{CollectiveTensorMap, get_peer_devices};
use crate::{
AllReduceStrategy, CollectiveConfig, CollectiveError, ReduceOperation,
local::{
all_reduce_sum_centralized, all_reduce_sum_ring, all_reduce_sum_tree,
broadcast_centralized, broadcast_tree, reduce_sum_centralized, reduce_sum_tree,
},
node::base::Node,
};
use ruda_tensor::Backend;
use ruda_communication::Protocol;
#[cfg(feature = "tracing")]
use tracing::Instrument;
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(tensors, config))
)]
pub(crate) async fn all_reduce_local_only<B: Backend>(
tensors: CollectiveTensorMap<B>,
op: ReduceOperation,
config: &CollectiveConfig,
) -> Result<CollectiveTensorMap<B>, CollectiveError> {
let local_strategy = &config.local_all_reduce_strategy;
let mut reduced_tensors = match local_strategy {
AllReduceStrategy::Centralized => all_reduce_sum_centralized::<B>(tensors),
AllReduceStrategy::Tree(arity) => all_reduce_sum_tree::<B>(tensors, *arity),
AllReduceStrategy::Ring => all_reduce_sum_ring::<B>(tensors),
};
if op == ReduceOperation::Mean {
#[cfg(feature = "tracing")]
let _span = tracing::info_span!("mean_reduction").entered();
let div = (reduced_tensors.len() as f32).into();
reduced_tensors = reduced_tensors
.into_iter()
.map(|(id, t)| (id, B::float_div_scalar(t, div)))
.collect();
}
Ok(reduced_tensors)
}
#[cfg_attr(
feature = "tracing",
tracing::instrument(level = "trace", skip(tensors, config, global_client))
)]
pub(crate) async fn all_reduce_with_global<B: Backend, P: Protocol>(
tensors: CollectiveTensorMap<B>,
op: ReduceOperation,
config: &CollectiveConfig,
global_client: &mut Node<B, P>,
) -> Result<CollectiveTensorMap<B>, CollectiveError> {
let peer_devices = get_peer_devices::<B>(&tensors);
let main_device = *tensors.keys().next().unwrap();
let mut main_tensor = match config.local_all_reduce_strategy {
AllReduceStrategy::Centralized => reduce_sum_centralized::<B>(tensors, &main_device),
AllReduceStrategy::Tree(arity) => reduce_sum_tree::<B>(tensors, &main_device, arity),
AllReduceStrategy::Ring => all_reduce_sum_ring::<B>(tensors)
.remove(&main_device)
.unwrap(),
};
main_tensor = {
let fut = async {
let global_strategy = config
.global_all_reduce_strategy
.expect("global_all_reduce_strategy must be set");
global_client
.all_reduce(main_tensor, global_strategy, op)
.await
};
#[cfg(feature = "tracing")]
{
fut.instrument(tracing::info_span!("global_all_reduce"))
}
#[cfg(not(feature = "tracing"))]
{
fut
}
}
.await
.map_err(CollectiveError::Global)?;
let tensors = match config.local_all_reduce_strategy {
AllReduceStrategy::Tree(arity) => {
broadcast_tree::<B>(peer_devices, main_device, main_tensor, arity)
}
AllReduceStrategy::Centralized | AllReduceStrategy::Ring => {
broadcast_centralized::<B>(peer_devices, main_device, main_tensor)
}
};
Ok(tensors)
}