ruCCL 0.21.1

Ruda collective communication algorithms and orchestration.
Documentation
use super::error::RankError;
use super::{ElementType, FLAG_COUNTS_PREFIX, Frame, NetworkError};

#[cfg(test)]
mod tests;

pub fn validate_host_reduction_payload(
    element_type: ElementType,
    element_count: usize,
    payload: &[u8],
) -> Result<usize, RankError> {
    let element_bytes = element_type.byte_width();
    if element_bytes == 0 {
        return Err(RankError::InvalidLength(
            "host reduction requires a tensor element type",
        ));
    }
    let expected = element_count
        .checked_mul(element_bytes)
        .ok_or(RankError::Overflow("host reduction payload bytes"))?;
    if payload.len() != expected {
        return Err(NetworkError::InvalidConfiguration(format!(
            "host reduction payload has {} bytes, expected {expected}",
            payload.len()
        ))
        .into());
    }
    Ok(expected)
}

pub fn validate_host_reduction_response(
    operation: &str,
    payload: &[u8],
    expected: usize,
) -> Result<(), RankError> {
    if payload.len() != expected {
        return Err(NetworkError::InvalidConfiguration(format!(
            "host {operation} response has {} bytes, expected {expected}",
            payload.len()
        ))
        .into());
    }
    Ok(())
}

pub fn decode_exact<T, E: From<RankError>>(
    payload: &[u8],
    expected_elements: usize,
    element_bytes: usize,
    decode: impl FnOnce(&[u8]) -> Result<Vec<T>, E>,
) -> Result<Vec<T>, E> {
    let expected_bytes = expected_elements
        .checked_mul(element_bytes)
        .ok_or(RankError::Overflow("TCP decoded payload bytes"))?;
    if payload.len() != expected_bytes {
        return Err(
            RankError::Network(NetworkError::InvalidConfiguration(format!(
                "TCP response has {} bytes, expected {expected_bytes}",
                payload.len()
            )))
            .into(),
        );
    }
    decode(payload)
}

pub fn encode_counts(counts: &[usize]) -> Result<Vec<u8>, RankError> {
    let mut encoded = Vec::with_capacity(counts.len().saturating_mul(8));
    for count in counts {
        encoded.extend_from_slice(
            &u64::try_from(*count)
                .map_err(|_| RankError::Overflow("TCP all-to-all-v count"))?
                .to_le_bytes(),
        );
    }
    Ok(encoded)
}

pub fn decode_counts_response(
    response: &Frame,
    world_size: usize,
    element_bytes: usize,
) -> Result<(Vec<usize>, &[u8]), RankError> {
    if response.header.flags & FLAG_COUNTS_PREFIX == 0 {
        return Err(NetworkError::InvalidConfiguration(
            "TCP all-to-all-v response is missing counts".into(),
        )
        .into());
    }
    let prefix_bytes = world_size
        .checked_mul(8)
        .ok_or(RankError::Overflow("TCP all-to-all-v counts prefix"))?;
    if response.payload.len() < prefix_bytes {
        return Err(NetworkError::InvalidConfiguration(
            "TCP all-to-all-v counts prefix is truncated".into(),
        )
        .into());
    }
    let counts = response.payload[..prefix_bytes]
        .chunks_exact(8)
        .map(|bytes| {
            usize::try_from(u64::from_le_bytes(bytes.try_into().unwrap()))
                .map_err(|_| RankError::Overflow("TCP all-to-all-v receive count"))
        })
        .collect::<Result<Vec<_>, _>>()?;
    let total = counts
        .iter()
        .try_fold(0_usize, |sum, count| sum.checked_add(*count))
        .ok_or(RankError::Overflow("TCP all-to-all-v receive count"))?;
    if total as u64 != response.header.element_count {
        return Err(NetworkError::InvalidConfiguration(format!(
            "TCP all-to-all-v counts sum to {total}, header declares {}",
            response.header.element_count
        ))
        .into());
    }
    let data = &response.payload[prefix_bytes..];
    let expected = total
        .checked_mul(element_bytes)
        .ok_or(RankError::Overflow("TCP all-to-all-v data"))?;
    if data.len() != expected {
        return Err(NetworkError::InvalidConfiguration(format!(
            "TCP all-to-all-v data has {} bytes, expected {expected}",
            data.len()
        ))
        .into());
    }
    Ok((counts, data))
}