1use std::{collections::BTreeSet, ops::Range};
9
10use eredu_core::{
11 checkpoint::TensorDtype, consensus::ConsensusTransport, CollectiveGroupDescriptor,
12 CollectiveGroupId, CompletionCancellationMode, ParallelAxis, ParallelRankTopology,
13 ParallelTopology,
14};
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
22pub struct CommunicationPeerCounts {
23 send: Vec<usize>,
24 receive: Vec<usize>,
25}
26
27impl CommunicationPeerCounts {
28 pub fn new(
30 send: Vec<usize>,
31 receive: Vec<usize>,
32 group_size: usize,
33 ) -> Result<Self, CommunicationManifestError> {
34 if group_size == 0 || send.len() != group_size || receive.len() != group_size {
35 return Err(CommunicationManifestError::InvalidPeerCounts {
36 group_size,
37 send: send.len(),
38 receive: receive.len(),
39 });
40 }
41 Ok(Self { send, receive })
42 }
43
44 pub fn send(&self) -> &[usize] {
46 &self.send
47 }
48
49 pub fn receive(&self) -> &[usize] {
51 &self.receive
52 }
53
54 pub fn group_size(&self) -> usize {
56 self.send.len()
57 }
58}
59
60impl<'de> Deserialize<'de> for CommunicationPeerCounts {
61 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62 where
63 D: serde::Deserializer<'de>,
64 {
65 #[derive(Deserialize)]
66 struct Raw {
67 send: Vec<usize>,
68 receive: Vec<usize>,
69 }
70
71 let raw = Raw::deserialize(deserializer)?;
72 let group_size = raw.send.len();
73 Self::new(raw.send, raw.receive, group_size).map_err(serde::de::Error::custom)
74 }
75}
76
77#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
79#[serde(transparent)]
80pub struct CommunicationRouteId(u64);
81
82impl CommunicationRouteId {
83 pub const fn new(value: u64) -> Self {
85 Self(value)
86 }
87
88 pub const fn value(self) -> u64 {
90 self.0
91 }
92}
93
94#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
96#[serde(rename_all = "snake_case")]
97#[non_exhaustive]
98pub enum CommunicationOperation {
99 AllReduceSum,
101 AllGatherEven,
103 AllGatherUneven,
105 VariableAllToAll,
107 SendReceive,
109 Broadcast,
111 Barrier,
113 FailureAgreement,
115}
116
117#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize)]
119pub struct CommunicationTensorLimits {
120 max_tensors: usize,
121 max_tensor_rank: usize,
122 max_tensor_elements: usize,
123 max_output_tensor_elements: usize,
124 max_count_per_peer: Option<usize>,
125}
126
127impl<'de> Deserialize<'de> for CommunicationTensorLimits {
128 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
129 where
130 D: serde::Deserializer<'de>,
131 {
132 #[derive(Deserialize)]
133 struct Raw {
134 max_tensors: usize,
135 max_tensor_rank: usize,
136 max_tensor_elements: usize,
137 #[serde(default)]
138 max_output_tensor_elements: Option<usize>,
139 max_count_per_peer: Option<usize>,
140 }
141
142 let raw = Raw::deserialize(deserializer)?;
143 let limits = Self::new(
144 raw.max_tensors,
145 raw.max_tensor_rank,
146 raw.max_tensor_elements,
147 raw.max_count_per_peer,
148 )
149 .map_err(serde::de::Error::custom)?;
150 match raw.max_output_tensor_elements {
151 Some(elements) => limits
152 .with_output_tensor_elements(elements)
153 .map_err(serde::de::Error::custom),
154 None => Ok(limits),
155 }
156 }
157}
158
159impl CommunicationTensorLimits {
160 pub fn new(
162 max_tensors: usize,
163 max_tensor_rank: usize,
164 max_tensor_elements: usize,
165 max_count_per_peer: Option<usize>,
166 ) -> Result<Self, CommunicationManifestError> {
167 if max_tensors == 0 || max_tensor_elements == 0 || max_count_per_peer == Some(0) {
168 return Err(CommunicationManifestError::InvalidOperationLimits);
169 }
170 Ok(Self {
171 max_tensors,
172 max_tensor_rank,
173 max_tensor_elements,
174 max_output_tensor_elements: max_tensor_elements,
175 max_count_per_peer,
176 })
177 }
178
179 pub fn with_output_tensor_elements(
183 mut self,
184 max_output_tensor_elements: usize,
185 ) -> Result<Self, CommunicationManifestError> {
186 if max_output_tensor_elements == 0 {
187 return Err(CommunicationManifestError::InvalidOperationLimits);
188 }
189 self.max_output_tensor_elements = max_output_tensor_elements;
190 Ok(self)
191 }
192
193 pub const fn max_tensors(self) -> usize {
195 self.max_tensors
196 }
197
198 pub const fn max_tensor_rank(self) -> usize {
200 self.max_tensor_rank
201 }
202
203 pub const fn max_tensor_elements(self) -> usize {
205 self.max_tensor_elements
206 }
207
208 pub const fn max_output_tensor_elements(self) -> usize {
210 self.max_output_tensor_elements
211 }
212
213 pub const fn max_count_per_peer(self) -> Option<usize> {
215 self.max_count_per_peer
216 }
217
218 fn covers(self, required: Self) -> bool {
219 self.max_tensors >= required.max_tensors
220 && self.max_tensor_rank >= required.max_tensor_rank
221 && self.max_tensor_elements >= required.max_tensor_elements
222 && self.max_output_tensor_elements >= required.max_output_tensor_elements
223 && match (self.max_count_per_peer, required.max_count_per_peer) {
224 (_, None) => true,
225 (Some(available), Some(required)) => available >= required,
226 (None, Some(_)) => false,
227 }
228 }
229}
230
231#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
233pub struct CommunicationOperationRequirement {
234 operation: CommunicationOperation,
235 dtypes: Vec<TensorDtype>,
236 limits: Option<CommunicationTensorLimits>,
237 exact_completion: bool,
238}
239
240impl CommunicationOperationRequirement {
241 pub fn tensors(
243 operation: CommunicationOperation,
244 dtypes: impl IntoIterator<Item = TensorDtype>,
245 limits: CommunicationTensorLimits,
246 exact_completion: bool,
247 ) -> Result<Self, CommunicationManifestError> {
248 if matches!(
249 operation,
250 CommunicationOperation::Barrier | CommunicationOperation::FailureAgreement
251 ) {
252 return Err(CommunicationManifestError::InvalidOperationLimits);
253 }
254 if operation == CommunicationOperation::VariableAllToAll
255 && limits.max_count_per_peer().is_none()
256 {
257 return Err(CommunicationManifestError::InvalidOperationLimits);
258 }
259 if operation != CommunicationOperation::VariableAllToAll
260 && limits.max_count_per_peer().is_some()
261 {
262 return Err(CommunicationManifestError::InvalidOperationLimits);
263 }
264 let dtypes = dtypes.into_iter().collect::<Vec<_>>();
265 if dtypes.is_empty() || contains_duplicate_dtypes(&dtypes) {
266 return Err(CommunicationManifestError::InvalidOperationDtypes);
267 }
268 Ok(Self {
269 operation,
270 dtypes,
271 limits: Some(limits),
272 exact_completion,
273 })
274 }
275
276 pub const fn barrier(exact_completion: bool) -> Self {
278 Self {
279 operation: CommunicationOperation::Barrier,
280 dtypes: Vec::new(),
281 limits: None,
282 exact_completion,
283 }
284 }
285
286 pub const fn failure_agreement(exact_completion: bool) -> Self {
288 Self {
289 operation: CommunicationOperation::FailureAgreement,
290 dtypes: Vec::new(),
291 limits: None,
292 exact_completion,
293 }
294 }
295
296 pub const fn operation(&self) -> CommunicationOperation {
298 self.operation
299 }
300
301 pub fn dtypes(&self) -> &[TensorDtype] {
303 &self.dtypes
304 }
305
306 pub const fn limits(&self) -> Option<CommunicationTensorLimits> {
308 self.limits
309 }
310
311 pub const fn exact_completion(&self) -> bool {
313 self.exact_completion
314 }
315
316 fn validate(&self) -> Result<(), CommunicationManifestError> {
317 match (self.operation, self.limits) {
318 (CommunicationOperation::Barrier | CommunicationOperation::FailureAgreement, None)
319 if self.dtypes.is_empty() =>
320 {
321 Ok(())
322 }
323 (CommunicationOperation::VariableAllToAll, Some(limits))
324 if limits.max_count_per_peer().is_some()
325 && !self.dtypes.is_empty()
326 && !contains_duplicate_dtypes(&self.dtypes) =>
327 {
328 Ok(())
329 }
330 (operation, Some(limits))
331 if operation != CommunicationOperation::Barrier
332 && operation != CommunicationOperation::FailureAgreement
333 && operation != CommunicationOperation::VariableAllToAll
334 && limits.max_count_per_peer().is_none()
335 && !self.dtypes.is_empty()
336 && !contains_duplicate_dtypes(&self.dtypes) =>
337 {
338 Ok(())
339 }
340 _ => Err(CommunicationManifestError::InvalidOperationLimits),
341 }
342 }
343}
344
345impl<'de> Deserialize<'de> for CommunicationOperationRequirement {
346 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
347 where
348 D: serde::Deserializer<'de>,
349 {
350 #[derive(Deserialize)]
351 struct Raw {
352 operation: CommunicationOperation,
353 dtypes: Vec<TensorDtype>,
354 limits: Option<CommunicationTensorLimits>,
355 exact_completion: bool,
356 }
357
358 let raw = Raw::deserialize(deserializer)?;
359 let requirement = Self {
360 operation: raw.operation,
361 dtypes: raw.dtypes,
362 limits: raw.limits,
363 exact_completion: raw.exact_completion,
364 };
365 requirement.validate().map_err(serde::de::Error::custom)?;
366 Ok(requirement)
367 }
368}
369
370#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
372pub struct CommunicationGroupRequirements {
373 operations: Vec<CommunicationOperationRequirement>,
374}
375
376impl<'de> Deserialize<'de> for CommunicationGroupRequirements {
377 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
378 where
379 D: serde::Deserializer<'de>,
380 {
381 #[derive(Deserialize)]
382 struct Raw {
383 operations: Vec<CommunicationOperationRequirement>,
384 }
385
386 let raw = Raw::deserialize(deserializer)?;
387 Self::new(raw.operations).map_err(serde::de::Error::custom)
388 }
389}
390
391impl CommunicationGroupRequirements {
392 pub fn new(
394 operations: impl IntoIterator<Item = CommunicationOperationRequirement>,
395 ) -> Result<Self, CommunicationManifestError> {
396 let operations = operations.into_iter().collect::<Vec<_>>();
397 let mut seen = BTreeSet::new();
398 if operations.is_empty()
399 || operations.iter().any(|requirement| {
400 requirement.validate().is_err() || !seen.insert(requirement.operation())
401 })
402 {
403 return Err(CommunicationManifestError::DuplicateOrMissingOperation);
404 }
405 Ok(Self { operations })
406 }
407
408 pub fn operations(&self) -> &[CommunicationOperationRequirement] {
410 &self.operations
411 }
412}
413
414#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
416pub struct CommunicationGroupDescriptor {
417 id: CollectiveGroupId,
418 creation_order: usize,
419 members: Vec<usize>,
420 local_index: Option<usize>,
421 requirements: CommunicationGroupRequirements,
422}
423
424impl CommunicationGroupDescriptor {
425 pub fn new(
427 id: CollectiveGroupId,
428 creation_order: usize,
429 members: Vec<usize>,
430 local_index: Option<usize>,
431 requirements: CommunicationGroupRequirements,
432 ) -> Result<Self, CommunicationManifestError> {
433 let unique = members.iter().copied().collect::<BTreeSet<_>>();
434 if members.is_empty() {
435 return Err(CommunicationManifestError::EmptyGroup { id });
436 }
437 if unique.len() != members.len() {
438 return Err(CommunicationManifestError::DuplicateGroupMember { id });
439 }
440 if local_index.is_some_and(|index| index >= members.len()) {
441 return Err(CommunicationManifestError::WrongLocalIndex { id });
442 }
443 Ok(Self {
444 id,
445 creation_order,
446 members,
447 local_index,
448 requirements,
449 })
450 }
451
452 pub const fn id(&self) -> CollectiveGroupId {
454 self.id
455 }
456
457 pub const fn creation_order(&self) -> usize {
459 self.creation_order
460 }
461
462 pub fn members(&self) -> &[usize] {
464 &self.members
465 }
466
467 pub const fn local_index(&self) -> Option<usize> {
469 self.local_index
470 }
471
472 pub const fn requirements(&self) -> &CommunicationGroupRequirements {
474 &self.requirements
475 }
476
477 pub fn collective_descriptor(&self) -> Option<CollectiveGroupDescriptor> {
482 self.local_index.map(|local_index| {
483 CollectiveGroupDescriptor::new(self.id, self.members.clone(), local_index)
484 .expect("runtime communication descriptor already validates local membership")
485 })
486 }
487}
488
489impl<'de> Deserialize<'de> for CommunicationGroupDescriptor {
490 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
491 where
492 D: serde::Deserializer<'de>,
493 {
494 #[derive(Deserialize)]
495 struct Raw {
496 id: CollectiveGroupId,
497 creation_order: usize,
498 members: Vec<usize>,
499 local_index: Option<usize>,
500 requirements: CommunicationGroupRequirements,
501 }
502
503 let raw = Raw::deserialize(deserializer)?;
504 Self::new(
505 raw.id,
506 raw.creation_order,
507 raw.members,
508 raw.local_index,
509 raw.requirements,
510 )
511 .map_err(serde::de::Error::custom)
512 }
513}
514
515#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
517pub struct CommunicationRouteDescriptor {
518 id: CommunicationRouteId,
519 submission_order: usize,
520 source: usize,
521 destination: usize,
522 requirement: CommunicationOperationRequirement,
523 boundary: Option<RoleExactBoundaryContract>,
524}
525
526#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
528#[serde(rename_all = "snake_case")]
529pub enum BoundaryFramingProtocol {
530 RoleExactV1,
532}
533
534#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
536pub struct BoundaryRoleContract {
537 role: String,
538 dtype: TensorDtype,
539 shape: Vec<BoundaryDimensionContract>,
540}
541
542impl<'de> Deserialize<'de> for BoundaryRoleContract {
543 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
544 where
545 D: serde::Deserializer<'de>,
546 {
547 #[derive(Deserialize)]
548 struct Raw {
549 role: String,
550 dtype: TensorDtype,
551 shape: Vec<BoundaryDimensionContract>,
552 }
553
554 let raw = Raw::deserialize(deserializer)?;
555 Self::symbolic(raw.role, raw.dtype, raw.shape).map_err(serde::de::Error::custom)
556 }
557}
558
559#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
561#[serde(rename_all = "snake_case")]
562pub enum BoundaryDimensionContract {
563 Variable {
565 maximum: usize,
567 },
568 Fixed(usize),
570}
571
572impl BoundaryRoleContract {
573 pub fn new(
575 role: impl Into<String>,
576 dtype: TensorDtype,
577 shape: Vec<usize>,
578 ) -> Result<Self, CommunicationManifestError> {
579 let role = role.into();
580 if role.trim().is_empty() || shape.is_empty() || shape.contains(&0) {
581 return Err(CommunicationManifestError::InvalidBoundaryContract);
582 }
583 tensor_dtype_width(&dtype).ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
584 Ok(Self {
585 role,
586 dtype,
587 shape: shape
588 .into_iter()
589 .map(BoundaryDimensionContract::Fixed)
590 .collect(),
591 })
592 }
593
594 pub fn symbolic(
596 role: impl Into<String>,
597 dtype: TensorDtype,
598 shape: Vec<BoundaryDimensionContract>,
599 ) -> Result<Self, CommunicationManifestError> {
600 let role = role.into();
601 if role.trim().is_empty()
602 || shape.is_empty()
603 || shape.iter().any(|dimension| match dimension {
604 BoundaryDimensionContract::Variable { maximum } => *maximum == 0,
605 BoundaryDimensionContract::Fixed(value) => *value == 0,
606 })
607 {
608 return Err(CommunicationManifestError::InvalidBoundaryContract);
609 }
610 tensor_dtype_width(&dtype).ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
611 Ok(Self { role, dtype, shape })
612 }
613
614 pub fn role(&self) -> &str {
616 &self.role
617 }
618 pub const fn dtype(&self) -> &TensorDtype {
620 &self.dtype
621 }
622 pub fn shape(&self) -> &[BoundaryDimensionContract] {
624 &self.shape
625 }
626}
627
628#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
630pub struct RoleExactBoundaryContract {
631 protocol: BoundaryFramingProtocol,
632 schema: String,
633 roles: Vec<BoundaryRoleContract>,
634}
635
636impl<'de> Deserialize<'de> for RoleExactBoundaryContract {
637 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
638 where
639 D: serde::Deserializer<'de>,
640 {
641 #[derive(Deserialize)]
642 struct Raw {
643 protocol: BoundaryFramingProtocol,
644 schema: String,
645 roles: Vec<BoundaryRoleContract>,
646 }
647
648 let raw = Raw::deserialize(deserializer)?;
649 if raw.protocol != BoundaryFramingProtocol::RoleExactV1 {
650 return Err(serde::de::Error::custom(
651 CommunicationManifestError::InvalidBoundaryContract,
652 ));
653 }
654 Self::new(raw.schema, raw.roles).map_err(serde::de::Error::custom)
655 }
656}
657
658impl RoleExactBoundaryContract {
659 pub fn new(
661 schema: impl Into<String>,
662 roles: impl IntoIterator<Item = BoundaryRoleContract>,
663 ) -> Result<Self, CommunicationManifestError> {
664 let schema = schema.into();
665 let roles = roles.into_iter().collect::<Vec<_>>();
666 let mut names = BTreeSet::new();
667 if schema.trim().is_empty()
668 || roles.is_empty()
669 || roles.iter().any(|role| !names.insert(role.role()))
670 {
671 return Err(CommunicationManifestError::InvalidBoundaryContract);
672 }
673 Ok(Self {
674 protocol: BoundaryFramingProtocol::RoleExactV1,
675 schema,
676 roles,
677 })
678 }
679
680 pub fn schema(&self) -> &str {
682 &self.schema
683 }
684 pub fn roles(&self) -> &[BoundaryRoleContract] {
686 &self.roles
687 }
688
689 fn validate_actual_roles(
690 &self,
691 actual_roles: &[BoundaryRoleContract],
692 ) -> Result<(), CommunicationManifestError> {
693 if actual_roles.len() != self.roles.len() {
694 return Err(CommunicationManifestError::InvalidBoundaryContract);
695 }
696 for (actual, admitted) in actual_roles.iter().zip(&self.roles) {
697 if actual.role != admitted.role
698 || actual.dtype != admitted.dtype
699 || actual.shape.len() != admitted.shape.len()
700 || actual
701 .shape
702 .iter()
703 .zip(&admitted.shape)
704 .any(|(actual, admitted)| {
705 let BoundaryDimensionContract::Fixed(actual) = actual else {
706 return true;
707 };
708 match admitted {
709 BoundaryDimensionContract::Variable { maximum } => actual > maximum,
710 BoundaryDimensionContract::Fixed(expected) => actual != expected,
711 }
712 })
713 {
714 return Err(CommunicationManifestError::InvalidBoundaryContract);
715 }
716 }
717 Ok(())
718 }
719
720 pub fn validate_invocation(
722 &self,
723 actual_roles: &[BoundaryRoleContract],
724 ) -> Result<(), CommunicationManifestError> {
725 self.validate_actual_roles(actual_roles)
726 }
727
728 pub fn frame_values<T>(
730 &self,
731 route: CommunicationRouteId,
732 actual_roles: &[BoundaryRoleContract],
733 values: Vec<T>,
734 ) -> Result<Vec<crate::RoleExactBoundaryValue<T>>, CommunicationManifestError> {
735 if values.len() != self.roles.len() {
736 return Err(CommunicationManifestError::InvalidBoundaryContract);
737 }
738 self.validate_actual_roles(actual_roles)?;
739 values
740 .into_iter()
741 .zip(actual_roles)
742 .enumerate()
743 .map(|(ordinal, (tensor, actual))| {
744 Ok(crate::RoleExactBoundaryValue::new(
745 boundary_frame_header(route, &self.schema, ordinal, actual)?,
746 tensor,
747 ))
748 })
749 .collect()
750 }
751}
752
753impl CommunicationRouteDescriptor {
754 pub fn new(
756 id: CommunicationRouteId,
757 submission_order: usize,
758 source: usize,
759 destination: usize,
760 requirement: CommunicationOperationRequirement,
761 ) -> Result<Self, CommunicationManifestError> {
762 if source == destination {
763 return Err(CommunicationManifestError::InvalidRouteEndpoints { id });
764 }
765 if requirement.operation() != CommunicationOperation::SendReceive {
766 return Err(CommunicationManifestError::InvalidRouteOperation { id });
767 }
768 requirement.validate()?;
769 Ok(Self {
770 id,
771 submission_order,
772 source,
773 destination,
774 requirement,
775 boundary: None,
776 })
777 }
778
779 pub fn with_boundary_contract(
781 mut self,
782 boundary: RoleExactBoundaryContract,
783 ) -> Result<Self, CommunicationManifestError> {
784 let Some(limits) = self.requirement.limits() else {
785 return Err(CommunicationManifestError::InvalidBoundaryContract);
786 };
787 if !self.requirement.exact_completion() || boundary.roles().len() > limits.max_tensors() {
788 return Err(CommunicationManifestError::InvalidBoundaryContract);
789 }
790 let mut aggregate_bytes = 0usize;
791 for role in boundary.roles() {
792 if !self.requirement.dtypes().contains(role.dtype())
793 || role.shape().len() > limits.max_tensor_rank()
794 {
795 return Err(CommunicationManifestError::InvalidBoundaryContract);
796 }
797 let elements = role
798 .shape()
799 .iter()
800 .try_fold(1usize, |elements, dimension| {
801 let extent = match dimension {
802 BoundaryDimensionContract::Variable { maximum } => *maximum,
803 BoundaryDimensionContract::Fixed(value) => *value,
804 };
805 elements.checked_mul(extent)
806 })
807 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
808 if elements > limits.max_tensor_elements()
809 || elements > limits.max_output_tensor_elements()
810 {
811 return Err(CommunicationManifestError::InvalidBoundaryContract);
812 }
813 let bytes = elements
814 .checked_mul(
815 tensor_dtype_width(role.dtype())
816 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?,
817 )
818 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
819 aggregate_bytes = aggregate_bytes
820 .checked_add(bytes)
821 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
822 }
823 self.boundary = Some(boundary);
824 Ok(self)
825 }
826
827 pub const fn id(&self) -> CommunicationRouteId {
829 self.id
830 }
831
832 pub const fn submission_order(&self) -> usize {
834 self.submission_order
835 }
836
837 pub const fn source(&self) -> usize {
839 self.source
840 }
841
842 pub const fn destination(&self) -> usize {
844 self.destination
845 }
846
847 pub const fn requirement(&self) -> &CommunicationOperationRequirement {
849 &self.requirement
850 }
851
852 pub const fn boundary_contract(&self) -> Option<&RoleExactBoundaryContract> {
854 self.boundary.as_ref()
855 }
856}
857
858impl<'de> Deserialize<'de> for CommunicationRouteDescriptor {
859 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
860 where
861 D: serde::Deserializer<'de>,
862 {
863 #[derive(Deserialize)]
864 struct Raw {
865 id: CommunicationRouteId,
866 submission_order: usize,
867 source: usize,
868 destination: usize,
869 requirement: CommunicationOperationRequirement,
870 #[serde(default)]
871 boundary: Option<RoleExactBoundaryContract>,
872 }
873
874 let raw = Raw::deserialize(deserializer)?;
875 let route = Self::new(
876 raw.id,
877 raw.submission_order,
878 raw.source,
879 raw.destination,
880 raw.requirement,
881 )
882 .map_err(serde::de::Error::custom)?;
883 match raw.boundary {
884 Some(boundary) => route
885 .with_boundary_contract(boundary)
886 .map_err(serde::de::Error::custom),
887 None => Ok(route),
888 }
889 }
890}
891
892fn tensor_dtype_width(dtype: &TensorDtype) -> Option<usize> {
893 Some(match dtype {
894 TensorDtype::Bool | TensorDtype::I8 | TensorDtype::U8 => 1,
895 TensorDtype::F16 | TensorDtype::Bf16 | TensorDtype::U16 | TensorDtype::I16 => 2,
896 TensorDtype::F32 | TensorDtype::U32 | TensorDtype::I32 => 4,
897 TensorDtype::F64 | TensorDtype::U64 | TensorDtype::I64 | TensorDtype::Complex64 => 8,
898 TensorDtype::Encoded(_) => return None,
899 })
900}
901
902fn dtype_tag(dtype: &TensorDtype) -> Result<u8, CommunicationManifestError> {
903 Ok(match dtype {
904 TensorDtype::Bool => 0,
905 TensorDtype::F32 => 1,
906 TensorDtype::F16 => 2,
907 TensorDtype::Bf16 => 3,
908 TensorDtype::I8 => 4,
909 TensorDtype::U8 => 5,
910 TensorDtype::U16 => 6,
911 TensorDtype::U32 => 7,
912 TensorDtype::U64 => 8,
913 TensorDtype::I16 => 9,
914 TensorDtype::I32 => 10,
915 TensorDtype::I64 => 11,
916 TensorDtype::F64 => 12,
917 TensorDtype::Complex64 => 13,
918 TensorDtype::Encoded(_) => return Err(CommunicationManifestError::InvalidBoundaryContract),
919 })
920}
921
922fn boundary_frame_header(
923 route: CommunicationRouteId,
924 schema: &str,
925 ordinal: usize,
926 role: &BoundaryRoleContract,
927) -> Result<Vec<u8>, CommunicationManifestError> {
928 let exact_shape = role
929 .shape
930 .iter()
931 .map(|dimension| match dimension {
932 BoundaryDimensionContract::Fixed(value) => Ok(*value),
933 BoundaryDimensionContract::Variable { .. } => {
934 Err(CommunicationManifestError::InvalidBoundaryContract)
935 }
936 })
937 .collect::<Result<Vec<_>, _>>()?;
938 let payload_elements = exact_shape
939 .iter()
940 .try_fold(1usize, |value, dimension| value.checked_mul(*dimension))
941 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
942 let payload_bytes = payload_elements
943 .checked_mul(
944 tensor_dtype_width(&role.dtype)
945 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?,
946 )
947 .ok_or(CommunicationManifestError::InvalidBoundaryContract)?;
948 let ordinal =
949 u32::try_from(ordinal).map_err(|_| CommunicationManifestError::InvalidBoundaryContract)?;
950 let schema_len = u32::try_from(schema.len())
951 .map_err(|_| CommunicationManifestError::InvalidBoundaryContract)?;
952 let role_len = u32::try_from(role.role.len())
953 .map_err(|_| CommunicationManifestError::InvalidBoundaryContract)?;
954 let rank = u32::try_from(exact_shape.len())
955 .map_err(|_| CommunicationManifestError::InvalidBoundaryContract)?;
956 let payload_bytes = u64::try_from(payload_bytes)
957 .map_err(|_| CommunicationManifestError::InvalidBoundaryContract)?;
958 let mut header = b"EREDUBND".to_vec();
959 header.extend_from_slice(&1u16.to_le_bytes());
960 header.extend_from_slice(&route.value().to_le_bytes());
961 header.extend_from_slice(&ordinal.to_le_bytes());
962 header.push(dtype_tag(&role.dtype)?);
963 header.extend_from_slice(&schema_len.to_le_bytes());
964 header.extend_from_slice(schema.as_bytes());
965 header.extend_from_slice(&role_len.to_le_bytes());
966 header.extend_from_slice(role.role.as_bytes());
967 header.extend_from_slice(&rank.to_le_bytes());
968 for dimension in &exact_shape {
969 header.extend_from_slice(
970 &u64::try_from(*dimension)
971 .map_err(|_| CommunicationManifestError::InvalidBoundaryContract)?
972 .to_le_bytes(),
973 );
974 }
975 header.extend_from_slice(&payload_bytes.to_le_bytes());
976 Ok(header)
977}
978
979#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize)]
981pub struct CommunicationCompletionPolicy {
982 timeout_millis: u64,
983 cancellation: CompletionCancellationMode,
984}
985
986impl CommunicationCompletionPolicy {
987 pub fn new(
989 timeout: std::time::Duration,
990 cancellation: CompletionCancellationMode,
991 ) -> Result<Self, CommunicationManifestError> {
992 let timeout_millis = u64::try_from(timeout.as_millis())
993 .map_err(|_| CommunicationManifestError::InvalidCompletionPolicy)?;
994 if timeout_millis == 0 || std::time::Instant::now().checked_add(timeout).is_none() {
995 return Err(CommunicationManifestError::InvalidCompletionPolicy);
996 }
997 Ok(Self {
998 timeout_millis,
999 cancellation,
1000 })
1001 }
1002
1003 pub const fn timeout(self) -> std::time::Duration {
1005 std::time::Duration::from_millis(self.timeout_millis)
1006 }
1007
1008 pub const fn cancellation(self) -> CompletionCancellationMode {
1010 self.cancellation
1011 }
1012
1013 pub fn bounded_wait(self) -> eredu_core::BoundedCompletionWait {
1015 eredu_core::BoundedCompletionWait::new(self.timeout(), self.cancellation)
1016 .expect("checked communication completion policy has a positive timeout")
1017 }
1018}
1019
1020impl<'de> Deserialize<'de> for CommunicationCompletionPolicy {
1021 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1022 where
1023 D: serde::Deserializer<'de>,
1024 {
1025 #[derive(Deserialize)]
1026 struct Raw {
1027 timeout_millis: u64,
1028 cancellation: CompletionCancellationMode,
1029 }
1030
1031 let raw = Raw::deserialize(deserializer)?;
1032 Self::new(
1033 std::time::Duration::from_millis(raw.timeout_millis),
1034 raw.cancellation,
1035 )
1036 .map_err(serde::de::Error::custom)
1037 }
1038}
1039
1040#[derive(Debug, Clone, Eq, PartialEq)]
1042pub struct CommunicationCompletionCapabilities {
1043 cancellation_modes: Vec<CompletionCancellationMode>,
1044}
1045
1046impl CommunicationCompletionCapabilities {
1047 pub fn new(
1049 cancellation_modes: impl IntoIterator<Item = CompletionCancellationMode>,
1050 ) -> Result<Self, CommunicationManifestError> {
1051 let cancellation_modes = cancellation_modes.into_iter().collect::<Vec<_>>();
1052 let unique = cancellation_modes.iter().copied().collect::<BTreeSet<_>>();
1053 if cancellation_modes.is_empty() || unique.len() != cancellation_modes.len() {
1054 return Err(CommunicationManifestError::InvalidCompletionCapabilities);
1055 }
1056 Ok(Self { cancellation_modes })
1057 }
1058
1059 pub fn supports(&self, policy: CommunicationCompletionPolicy) -> bool {
1061 self.cancellation_modes.contains(&policy.cancellation())
1062 }
1063}
1064
1065#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
1067pub struct CommunicationManifest {
1068 world_size: usize,
1069 rank: usize,
1070 groups: Vec<CommunicationGroupDescriptor>,
1071 routes: Vec<CommunicationRouteDescriptor>,
1072 completion: Option<CommunicationCompletionPolicy>,
1073}
1074
1075impl CommunicationManifest {
1076 pub fn new(
1078 world_size: usize,
1079 rank: usize,
1080 groups: Vec<CommunicationGroupDescriptor>,
1081 routes: Vec<CommunicationRouteDescriptor>,
1082 ) -> Result<Self, CommunicationManifestError> {
1083 if world_size == 0 || rank >= world_size {
1084 return Err(CommunicationManifestError::RankOutOfRange { rank, world_size });
1085 }
1086 let mut group_ids = BTreeSet::new();
1087 for (order, group) in groups.iter().enumerate() {
1088 if !group_ids.insert(group.id()) {
1089 return Err(CommunicationManifestError::DuplicateGroupId { id: group.id() });
1090 }
1091 if group.creation_order() != order {
1092 return Err(CommunicationManifestError::WrongGroupOrder {
1093 id: group.id(),
1094 expected: order,
1095 actual: group.creation_order(),
1096 });
1097 }
1098 if group.members().iter().any(|member| *member >= world_size) {
1099 return Err(CommunicationManifestError::GroupMemberOutOfRange {
1100 id: group.id(),
1101 world_size,
1102 });
1103 }
1104 let expected = group.members().iter().position(|member| *member == rank);
1105 if group.local_index() != expected {
1106 return Err(CommunicationManifestError::WrongLocalIndex { id: group.id() });
1107 }
1108 }
1109
1110 let mut route_ids = BTreeSet::new();
1111 for (order, route) in routes.iter().enumerate() {
1112 if !route_ids.insert(route.id()) {
1113 return Err(CommunicationManifestError::DuplicateRouteId { id: route.id() });
1114 }
1115 if route.submission_order() != order {
1116 return Err(CommunicationManifestError::WrongRouteOrder {
1117 id: route.id(),
1118 expected: order,
1119 actual: route.submission_order(),
1120 });
1121 }
1122 if route.source() >= world_size || route.destination() >= world_size {
1123 return Err(CommunicationManifestError::RouteEndpointOutOfRange {
1124 id: route.id(),
1125 world_size,
1126 });
1127 }
1128 }
1129 Ok(Self {
1130 world_size,
1131 rank,
1132 groups,
1133 routes,
1134 completion: None,
1135 })
1136 }
1137
1138 pub fn with_completion_policy(mut self, policy: CommunicationCompletionPolicy) -> Self {
1140 self.completion = Some(policy);
1141 self
1142 }
1143
1144 pub const fn world_size(&self) -> usize {
1146 self.world_size
1147 }
1148
1149 pub const fn rank(&self) -> usize {
1151 self.rank
1152 }
1153
1154 pub fn groups(&self) -> &[CommunicationGroupDescriptor] {
1156 &self.groups
1157 }
1158
1159 pub fn routes(&self) -> &[CommunicationRouteDescriptor] {
1161 &self.routes
1162 }
1163
1164 pub(crate) fn route_submission_waves(&self) -> Vec<Range<usize>> {
1172 let mut waves = Vec::new();
1173 let mut start = 0;
1174 while start < self.routes.len() {
1175 let reference = &self.routes[start];
1176 let mut endpoints = vec![false; self.world_size];
1177 let mut end = start;
1178 while end < self.routes.len() {
1179 let route = &self.routes[end];
1180 if route.requirement() != reference.requirement()
1181 || route.boundary_contract() != reference.boundary_contract()
1182 || endpoints[route.source()]
1183 || endpoints[route.destination()]
1184 {
1185 break;
1186 }
1187 endpoints[route.source()] = true;
1188 endpoints[route.destination()] = true;
1189 end += 1;
1190 if endpoints.iter().all(|endpoint| *endpoint) {
1191 break;
1192 }
1193 }
1194 if !endpoints.iter().all(|endpoint| *endpoint) {
1195 end = start + 1;
1196 }
1197 waves.push(start..end);
1198 start = end;
1199 }
1200 waves
1201 }
1202
1203 pub const fn completion_policy(&self) -> Option<CommunicationCompletionPolicy> {
1205 self.completion
1206 }
1207}
1208
1209impl<'de> Deserialize<'de> for CommunicationManifest {
1210 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1211 where
1212 D: serde::Deserializer<'de>,
1213 {
1214 #[derive(Deserialize)]
1215 struct Raw {
1216 world_size: usize,
1217 rank: usize,
1218 groups: Vec<CommunicationGroupDescriptor>,
1219 routes: Vec<CommunicationRouteDescriptor>,
1220 #[serde(default)]
1221 completion: Option<CommunicationCompletionPolicy>,
1222 }
1223
1224 let raw = Raw::deserialize(deserializer)?;
1225 let manifest = Self::new(raw.world_size, raw.rank, raw.groups, raw.routes)
1226 .map_err(serde::de::Error::custom)?;
1227 Ok(match raw.completion {
1228 Some(policy) => manifest.with_completion_policy(policy),
1229 None => manifest,
1230 })
1231 }
1232}
1233
1234#[derive(Debug, Clone, Default, Eq, PartialEq)]
1236pub struct TopologyCommunicationPlan {
1237 session_group: Option<CommunicationGroupRequirements>,
1238 tensor_groups: Option<CommunicationGroupRequirements>,
1239 pipeline_groups: Option<CommunicationGroupRequirements>,
1240 expert_groups: Option<CommunicationGroupRequirements>,
1241 data_groups: Option<CommunicationGroupRequirements>,
1242 pipeline_routes: Option<CommunicationOperationRequirement>,
1243 completion: Option<CommunicationCompletionPolicy>,
1244}
1245
1246impl TopologyCommunicationPlan {
1247 pub const fn new() -> Self {
1249 Self {
1250 session_group: None,
1251 tensor_groups: None,
1252 pipeline_groups: None,
1253 expert_groups: None,
1254 data_groups: None,
1255 pipeline_routes: None,
1256 completion: None,
1257 }
1258 }
1259
1260 pub fn with_completion_policy(mut self, policy: CommunicationCompletionPolicy) -> Self {
1262 self.completion = Some(policy);
1263 self
1264 }
1265
1266 pub fn with_session_group(mut self, requirements: CommunicationGroupRequirements) -> Self {
1271 self.session_group = Some(requirements);
1272 self
1273 }
1274
1275 pub const fn session_group_id(&self) -> Option<CollectiveGroupId> {
1277 if self.session_group.is_some() {
1278 Some(CollectiveGroupId::new(1))
1279 } else {
1280 None
1281 }
1282 }
1283
1284 pub fn with_tensor_groups(mut self, requirements: CommunicationGroupRequirements) -> Self {
1286 self.tensor_groups = Some(requirements);
1287 self
1288 }
1289
1290 pub fn tensor_group_id(
1292 &self,
1293 topology: ParallelTopology,
1294 rank: ParallelRankTopology,
1295 ) -> Result<Option<CollectiveGroupId>, CommunicationManifestError> {
1296 if self.tensor_groups.is_none() {
1297 return Ok(None);
1298 }
1299 if rank.topology() != topology {
1300 return Err(CommunicationManifestError::TopologyMismatch);
1301 }
1302 let groups = unique_axis_groups(topology, ParallelAxis::Tensor)?;
1303 let subgroup = groups
1304 .iter()
1305 .position(|members| members.contains(&rank.global_rank()))
1306 .ok_or(CommunicationManifestError::InvalidTopologyProjection)?;
1307 let first = 1usize + usize::from(self.session_group.is_some());
1308 let numeric = first
1309 .checked_add(subgroup)
1310 .ok_or(CommunicationManifestError::DescriptorCountOverflow)?;
1311 Ok(Some(CollectiveGroupId::new(
1312 u32::try_from(numeric)
1313 .map_err(|_| CommunicationManifestError::DescriptorCountOverflow)?,
1314 )))
1315 }
1316
1317 pub fn with_pipeline_groups(mut self, requirements: CommunicationGroupRequirements) -> Self {
1319 self.pipeline_groups = Some(requirements);
1320 self
1321 }
1322
1323 pub fn with_expert_groups(mut self, requirements: CommunicationGroupRequirements) -> Self {
1325 self.expert_groups = Some(requirements);
1326 self
1327 }
1328
1329 pub fn with_data_groups(mut self, requirements: CommunicationGroupRequirements) -> Self {
1335 self.data_groups = Some(requirements);
1336 self
1337 }
1338
1339 pub fn with_pipeline_routes(
1341 mut self,
1342 requirement: CommunicationOperationRequirement,
1343 ) -> Result<Self, CommunicationManifestError> {
1344 if requirement.operation() != CommunicationOperation::SendReceive {
1345 return Err(CommunicationManifestError::InvalidRouteOperation {
1346 id: CommunicationRouteId::new(0),
1347 });
1348 }
1349 self.pipeline_routes = Some(requirement);
1350 Ok(self)
1351 }
1352}
1353
1354pub fn project_communication_manifest(
1356 topology: ParallelTopology,
1357 rank: ParallelRankTopology,
1358 plan: &TopologyCommunicationPlan,
1359) -> Result<CommunicationManifest, CommunicationManifestError> {
1360 if rank.topology() != topology {
1361 return Err(CommunicationManifestError::TopologyMismatch);
1362 }
1363
1364 let mut groups = Vec::new();
1365 let mut next_group_id = 1usize;
1366 if let Some(requirements) = &plan.session_group {
1367 let id = CollectiveGroupId::new(1);
1368 groups.push(CommunicationGroupDescriptor::new(
1369 id,
1370 0,
1371 (0..topology.world_size()).collect(),
1372 Some(rank.global_rank()),
1373 requirements.clone(),
1374 )?);
1375 next_group_id = 2;
1376 }
1377 for (axis, requirements) in [
1378 (ParallelAxis::Tensor, plan.tensor_groups.as_ref()),
1379 (ParallelAxis::Pipeline, plan.pipeline_groups.as_ref()),
1380 (ParallelAxis::Expert, plan.expert_groups.as_ref()),
1381 (ParallelAxis::Data, plan.data_groups.as_ref()),
1382 ] {
1383 let Some(requirements) = requirements else {
1384 continue;
1385 };
1386 let axis_groups = unique_axis_groups(topology, axis)?;
1387 let (subgroup_index, members) = axis_groups
1388 .iter()
1389 .enumerate()
1390 .find(|(_, members)| members.contains(&rank.global_rank()))
1391 .ok_or(CommunicationManifestError::InvalidTopologyProjection)?;
1392 let numeric_id = next_group_id
1393 .checked_add(subgroup_index)
1394 .ok_or(CommunicationManifestError::DescriptorCountOverflow)?;
1395 let id = CollectiveGroupId::new(
1396 u32::try_from(numeric_id)
1397 .map_err(|_| CommunicationManifestError::DescriptorCountOverflow)?,
1398 );
1399 let local_index = members
1400 .iter()
1401 .position(|member| *member == rank.global_rank());
1402 groups.push(CommunicationGroupDescriptor::new(
1403 id,
1404 groups.len(),
1405 members.clone(),
1406 local_index,
1407 requirements.clone(),
1408 )?);
1409 next_group_id = next_group_id
1410 .checked_add(axis_groups.len())
1411 .ok_or(CommunicationManifestError::DescriptorCountOverflow)?;
1412 }
1413
1414 let mut routes = Vec::new();
1415 if let Some(requirement) = &plan.pipeline_routes {
1416 for source in 0..topology.world_size() {
1417 let coordinates = topology
1418 .coordinates(source)
1419 .map_err(|_| CommunicationManifestError::InvalidTopologyProjection)?;
1420 if coordinates.pipeline() + 1 == topology.pipeline() {
1421 continue;
1422 }
1423 let destination = topology
1424 .rank_for(coordinates.with_pipeline(coordinates.pipeline() + 1))
1425 .map_err(|_| CommunicationManifestError::InvalidTopologyProjection)?;
1426 let id = CommunicationRouteId::new(routes.len() as u64);
1427 routes.push(CommunicationRouteDescriptor::new(
1428 id,
1429 routes.len(),
1430 source,
1431 destination,
1432 requirement.clone(),
1433 )?);
1434 }
1435 }
1436
1437 let manifest =
1438 CommunicationManifest::new(topology.world_size(), rank.global_rank(), groups, routes)?;
1439 Ok(match plan.completion {
1440 Some(policy) => manifest.with_completion_policy(policy),
1441 None => manifest,
1442 })
1443}
1444
1445pub fn project_all_communication_manifests(
1447 topology: ParallelTopology,
1448 plan: &TopologyCommunicationPlan,
1449) -> Result<Vec<CommunicationManifest>, CommunicationManifestError> {
1450 let manifests = (0..topology.world_size())
1451 .map(|global_rank| {
1452 let rank = ParallelRankTopology::new(topology, global_rank)
1453 .map_err(|_| CommunicationManifestError::InvalidTopologyProjection)?;
1454 project_communication_manifest(topology, rank, plan)
1455 })
1456 .collect::<Result<Vec<_>, _>>()?;
1457 validate_compatible_communication_manifests(&manifests)?;
1458 Ok(manifests)
1459}
1460
1461pub fn validate_compatible_communication_manifests(
1463 manifests: &[CommunicationManifest],
1464) -> Result<(), CommunicationManifestError> {
1465 let Some(reference) = manifests.first() else {
1466 return Err(CommunicationManifestError::MissingRankManifest { rank: 0 });
1467 };
1468 if manifests.len() != reference.world_size() {
1469 return Err(CommunicationManifestError::WrongManifestCount {
1470 expected: reference.world_size(),
1471 actual: manifests.len(),
1472 });
1473 }
1474 let mut ranks = vec![None; reference.world_size()];
1475 for manifest in manifests {
1476 if manifest.world_size() != reference.world_size()
1477 || manifest.rank() >= reference.world_size()
1478 {
1479 return Err(CommunicationManifestError::IncompatibleRankManifest {
1480 rank: manifest.rank(),
1481 });
1482 }
1483 let rank = manifest.rank();
1484 if ranks[rank].replace(manifest).is_some() {
1485 return Err(CommunicationManifestError::DuplicateRankManifest { rank });
1486 }
1487 }
1488 let ranks = ranks
1489 .into_iter()
1490 .enumerate()
1491 .map(|(rank, manifest)| {
1492 manifest.ok_or(CommunicationManifestError::MissingRankManifest { rank })
1493 })
1494 .collect::<Result<Vec<_>, _>>()?;
1495 let group_count = reference.groups().len();
1496 let mut ids_across_orders = BTreeSet::new();
1497 for (rank, manifest) in ranks.iter().copied().enumerate() {
1498 if manifest.routes() != reference.routes()
1499 || manifest.groups().len() != group_count
1500 || manifest.completion_policy() != reference.completion_policy()
1501 {
1502 return Err(CommunicationManifestError::IncompatibleRankManifest { rank });
1503 }
1504 }
1505 for order in 0..group_count {
1506 let mut subgroup_ids = BTreeSet::new();
1507 let mut covered = vec![false; reference.world_size()];
1508 for (rank, manifest) in ranks.iter().copied().enumerate() {
1509 let group = &manifest.groups()[order];
1510 if group.creation_order() != order
1511 || group.local_index() != group.members().iter().position(|member| *member == rank)
1512 {
1513 return Err(CommunicationManifestError::IncompatibleRankManifest { rank });
1514 }
1515 if subgroup_ids.insert(group.id()) {
1516 if !ids_across_orders.insert(group.id()) {
1517 return Err(CommunicationManifestError::IncompatibleRankManifest { rank });
1518 }
1519 for member in group.members() {
1520 if covered[*member] {
1521 return Err(CommunicationManifestError::IncompatibleRankManifest { rank });
1522 }
1523 covered[*member] = true;
1524 }
1525 }
1526 for member in group.members() {
1527 if *member >= ranks.len() {
1528 return Err(CommunicationManifestError::IncompatibleRankManifest { rank });
1529 }
1530 let peer = &ranks[*member].groups()[order];
1531 if peer.id() != group.id()
1532 || peer.creation_order() != group.creation_order()
1533 || peer.members() != group.members()
1534 || peer.requirements() != group.requirements()
1535 {
1536 return Err(CommunicationManifestError::IncompatibleRankManifest {
1537 rank: *member,
1538 });
1539 }
1540 }
1541 }
1542 if covered.contains(&false) {
1543 return Err(CommunicationManifestError::IncompatibleRankManifest { rank: 0 });
1544 }
1545 }
1546 for (rank, manifest) in ranks.iter().copied().enumerate() {
1547 for group in manifest.groups() {
1548 if group.local_index().is_none() {
1549 return Err(CommunicationManifestError::IncompatibleRankManifest { rank });
1550 }
1551 }
1552 }
1553 Ok(())
1554}
1555
1556pub fn validate_communication_manifest_consensus<T: ConsensusTransport>(
1565 transport: &T,
1566 local: &CommunicationManifest,
1567) -> Result<Vec<CommunicationManifest>, CommunicationManifestConsensusError> {
1568 let participants = transport.participant_count();
1569 if participants == 0 {
1570 return Err(CommunicationManifestConsensusError::EmptyTopology);
1571 }
1572
1573 let encoded = serde_json::to_vec(local)
1574 .map_err(|error| CommunicationManifestConsensusError::Encoding(error.to_string()))?;
1575 let encoded_len = u64::try_from(encoded.len()).map_err(|_| {
1576 CommunicationManifestConsensusError::MetadataOverflow("encoded manifest length")
1577 })?;
1578 let length_words = [encoded_len as u32, (encoded_len >> 32) as u32];
1579 let gathered_lengths =
1580 gather_manifest_words(transport, &length_words, participants, "manifest lengths")?;
1581
1582 let lengths = gathered_lengths
1583 .as_chunks::<2>()
1584 .0
1585 .iter()
1586 .enumerate()
1587 .map(|(rank, words)| {
1588 let length = u64::from(words[0]) | (u64::from(words[1]) << 32);
1589 usize::try_from(length).map_err(|_| {
1590 CommunicationManifestConsensusError::PayloadLengthOverflow { rank, length }
1591 })
1592 })
1593 .collect::<Result<Vec<_>, _>>()?;
1594 let payload_words = lengths
1595 .iter()
1596 .copied()
1597 .map(words_for_bytes)
1598 .max()
1599 .unwrap_or(0);
1600 let local_words = encode_manifest_words(&encoded, payload_words);
1601 let gathered_payloads =
1602 gather_manifest_words(transport, &local_words, participants, "manifest payloads")?;
1603
1604 let mut manifests = Vec::with_capacity(participants);
1605 for (rank, &length) in lengths.iter().enumerate() {
1606 let available = payload_words.checked_mul(4).ok_or(
1607 CommunicationManifestConsensusError::MetadataOverflow("manifest payload bytes"),
1608 )?;
1609 if length > available {
1610 return Err(CommunicationManifestConsensusError::InvalidPayloadLength {
1611 rank,
1612 length,
1613 available,
1614 });
1615 }
1616 let start = rank.checked_mul(payload_words).ok_or(
1617 CommunicationManifestConsensusError::MetadataOverflow("manifest payload offset"),
1618 )?;
1619 let end = start.checked_add(payload_words).ok_or(
1620 CommunicationManifestConsensusError::MetadataOverflow("manifest payload end"),
1621 )?;
1622 let mut bytes = Vec::with_capacity(available);
1623 for word in &gathered_payloads[start..end] {
1624 bytes.extend_from_slice(&word.to_le_bytes());
1625 }
1626 bytes.truncate(length);
1627 manifests.push(serde_json::from_slice(&bytes).map_err(|error| {
1628 CommunicationManifestConsensusError::InvalidEncoding {
1629 rank,
1630 message: error.to_string(),
1631 }
1632 })?);
1633 }
1634
1635 validate_compatible_communication_manifests(&manifests)?;
1636 Ok(manifests)
1637}
1638
1639fn words_for_bytes(bytes: usize) -> usize {
1640 bytes / 4 + usize::from(!bytes.is_multiple_of(4))
1641}
1642
1643fn encode_manifest_words(encoded: &[u8], padded_words: usize) -> Vec<u32> {
1644 let mut words = Vec::with_capacity(padded_words);
1645 for chunk in encoded.chunks(4) {
1646 let mut word = [0; 4];
1647 word[..chunk.len()].copy_from_slice(chunk);
1648 words.push(u32::from_le_bytes(word));
1649 }
1650 words.resize(padded_words, 0);
1651 words
1652}
1653
1654fn gather_manifest_words<T: ConsensusTransport>(
1655 transport: &T,
1656 local: &[u32],
1657 participants: usize,
1658 stage: &'static str,
1659) -> Result<Vec<u32>, CommunicationManifestConsensusError> {
1660 let expected = local.len().checked_mul(participants).ok_or(
1661 CommunicationManifestConsensusError::MetadataOverflow("gathered manifest word count"),
1662 )?;
1663 let gathered = transport
1664 .all_gather_words(local)
1665 .map_err(|error| CommunicationManifestConsensusError::Transport(error.to_string()))?;
1666 if gathered.len() != expected {
1667 return Err(CommunicationManifestConsensusError::MalformedGather {
1668 stage,
1669 expected,
1670 actual: gathered.len(),
1671 participants,
1672 });
1673 }
1674 Ok(gathered)
1675}
1676
1677#[derive(Debug, Clone, Eq, PartialEq)]
1679pub struct CommunicationCapabilities {
1680 operations: Vec<CommunicationOperationRequirement>,
1681 completion: Option<CommunicationCompletionCapabilities>,
1682 boundary_framing: Vec<BoundaryFramingProtocol>,
1683}
1684
1685#[derive(Debug, Clone, Copy, Eq, PartialEq)]
1691pub enum CommunicationTopologyCapabilities {
1692 FullyConnected,
1695 RingWithWorldWaves,
1699}
1700
1701#[derive(Debug, Clone)]
1704pub struct PreparedCommunicationRealization {
1705 manifest: CommunicationManifest,
1706 group_world_waves: Vec<bool>,
1707 route_world_waves: Vec<bool>,
1708}
1709
1710impl PreparedCommunicationRealization {
1711 pub const fn manifest(&self) -> &CommunicationManifest {
1713 &self.manifest
1714 }
1715
1716 pub fn group_world_wave(&self, creation_order: usize) -> Option<bool> {
1718 self.group_world_waves.get(creation_order).copied()
1719 }
1720
1721 pub fn route_world_wave(&self, submission_order: usize) -> Option<bool> {
1723 self.route_world_waves.get(submission_order).copied()
1724 }
1725
1726 pub fn try_create_groups<T, E>(
1728 &self,
1729 mut create: impl FnMut(&CommunicationGroupDescriptor, bool) -> Result<T, E>,
1730 ) -> Result<Vec<T>, E> {
1731 self.manifest
1732 .groups()
1733 .iter()
1734 .zip(self.group_world_waves.iter().copied())
1735 .map(|(descriptor, world_wave)| create(descriptor, world_wave))
1736 .collect()
1737 }
1738
1739 pub fn try_create_routes<T, E>(
1741 &self,
1742 mut create: impl FnMut(&CommunicationRouteDescriptor, bool) -> Result<T, E>,
1743 ) -> Result<Vec<T>, E> {
1744 self.manifest
1745 .routes()
1746 .iter()
1747 .zip(self.route_world_waves.iter().copied())
1748 .map(|(descriptor, world_wave)| create(descriptor, world_wave))
1749 .collect()
1750 }
1751}
1752
1753#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
1756#[non_exhaustive]
1757pub enum CommunicationRealizationError {
1758 #[error(transparent)]
1760 Manifest(#[from] CommunicationManifestError),
1761 #[error(transparent)]
1763 Capability(#[from] CommunicationCapabilityError),
1764 #[error("local communication manifest differs from the agreed rank projection")]
1766 LocalManifestMismatch,
1767}
1768
1769pub fn prepare_communication_realization(
1772 manifest: &CommunicationManifest,
1773 compatible_manifests: &[CommunicationManifest],
1774 capabilities: &CommunicationCapabilities,
1775 topology: CommunicationTopologyCapabilities,
1776) -> Result<PreparedCommunicationRealization, CommunicationRealizationError> {
1777 validate_compatible_communication_manifests(compatible_manifests)?;
1778 let agreed = compatible_manifests
1779 .iter()
1780 .find(|candidate| candidate.rank() == manifest.rank())
1781 .ok_or(CommunicationRealizationError::LocalManifestMismatch)?;
1782 if agreed != manifest {
1783 return Err(CommunicationRealizationError::LocalManifestMismatch);
1784 }
1785 capabilities.validate_manifest(manifest)?;
1786
1787 let group_wave_proofs = compatible_group_world_wave_proofs(compatible_manifests);
1788 let route_wave_proofs = route_world_wave_proofs(manifest);
1789 let mut selected_group_waves = vec![false; manifest.groups().len()];
1790 let mut selected_route_waves = vec![false; manifest.routes().len()];
1791
1792 if topology == CommunicationTopologyCapabilities::RingWithWorldWaves {
1793 for (order, group) in manifest.groups().iter().enumerate() {
1794 let directly_reachable = group.members().len() <= 1
1795 || group.members().len() == manifest.world_size()
1796 || (group.members().len() == 2
1797 && ring_neighbors(
1798 group.members()[0],
1799 group.members()[1],
1800 manifest.world_size(),
1801 ));
1802 if !directly_reachable {
1803 if !group_wave_proofs.get(order).copied().unwrap_or(false) {
1804 return Err(
1805 CommunicationCapabilityError::UnreachableGroup { id: group.id() }.into(),
1806 );
1807 }
1808 selected_group_waves[order] = true;
1809 }
1810 }
1811 for (order, route) in manifest.routes().iter().enumerate() {
1812 if !ring_neighbors(route.source(), route.destination(), manifest.world_size()) {
1813 if !route_wave_proofs.get(order).copied().unwrap_or(false) {
1814 return Err(CommunicationCapabilityError::UnreachableRoute {
1815 id: route.id(),
1816 source_rank: route.source(),
1817 destination_rank: route.destination(),
1818 }
1819 .into());
1820 }
1821 selected_route_waves[order] = true;
1822 }
1823 }
1824 }
1825
1826 Ok(PreparedCommunicationRealization {
1827 manifest: manifest.clone(),
1828 group_world_waves: selected_group_waves,
1829 route_world_waves: selected_route_waves,
1830 })
1831}
1832
1833pub fn compatible_group_world_wave_proofs(manifests: &[CommunicationManifest]) -> Vec<bool> {
1838 let group_count = manifests
1839 .first()
1840 .map_or(0, |manifest| manifest.groups().len());
1841 (0..group_count)
1842 .map(|order| {
1843 let Some(requirements) = manifests
1844 .first()
1845 .and_then(|manifest| manifest.groups().get(order))
1846 .map(CommunicationGroupDescriptor::requirements)
1847 else {
1848 return false;
1849 };
1850 manifests.iter().all(|manifest| {
1851 manifest
1852 .groups()
1853 .get(order)
1854 .is_some_and(|group| group.requirements() == requirements)
1855 })
1856 })
1857 .collect()
1858}
1859
1860pub fn route_world_wave_proofs(manifest: &CommunicationManifest) -> Vec<bool> {
1865 let mut proofs = vec![false; manifest.routes().len()];
1866 for wave in manifest.route_submission_waves() {
1867 let mut members = vec![false; manifest.world_size()];
1868 for route in &manifest.routes()[wave.clone()] {
1869 members[route.source()] = true;
1870 members[route.destination()] = true;
1871 }
1872 if members.iter().all(|member| *member) {
1873 proofs[wave].fill(true);
1874 }
1875 }
1876 proofs
1877}
1878
1879fn ring_neighbors(left: usize, right: usize, world_size: usize) -> bool {
1880 world_size > 1 && ((left + 1) % world_size == right || (right + 1) % world_size == left)
1881}
1882
1883impl CommunicationCapabilities {
1884 pub fn new(
1886 operations: impl IntoIterator<Item = CommunicationOperationRequirement>,
1887 ) -> Result<Self, CommunicationManifestError> {
1888 let operations = operations.into_iter().collect::<Vec<_>>();
1889 let mut seen = BTreeSet::new();
1890 if operations.iter().any(|capability| {
1891 capability.validate().is_err() || !seen.insert(capability.operation())
1892 }) {
1893 return Err(CommunicationManifestError::DuplicateOrMissingOperation);
1894 }
1895 Ok(Self {
1896 operations,
1897 completion: None,
1898 boundary_framing: Vec::new(),
1899 })
1900 }
1901
1902 pub fn with_boundary_framing(
1904 mut self,
1905 protocols: impl IntoIterator<Item = BoundaryFramingProtocol>,
1906 ) -> Result<Self, CommunicationManifestError> {
1907 let protocols = protocols.into_iter().collect::<Vec<_>>();
1908 if protocols.is_empty()
1909 || protocols
1910 .iter()
1911 .enumerate()
1912 .any(|(index, protocol)| protocols[..index].contains(protocol))
1913 {
1914 return Err(CommunicationManifestError::InvalidBoundaryContract);
1915 }
1916 self.boundary_framing = protocols;
1917 Ok(self)
1918 }
1919
1920 pub fn with_completion_capabilities(
1922 mut self,
1923 completion: CommunicationCompletionCapabilities,
1924 ) -> Self {
1925 self.completion = Some(completion);
1926 self
1927 }
1928
1929 pub fn validate_manifest(
1931 &self,
1932 manifest: &CommunicationManifest,
1933 ) -> Result<(), CommunicationCapabilityError> {
1934 if !manifest.groups().is_empty() || !manifest.routes().is_empty() {
1935 let policy = manifest
1936 .completion_policy()
1937 .ok_or(CommunicationCapabilityError::MissingSelectedCompletionPolicy)?;
1938 let completion = self
1939 .completion
1940 .as_ref()
1941 .ok_or(CommunicationCapabilityError::MissingBoundedCompletion)?;
1942 if !completion.supports(policy) {
1943 return Err(CommunicationCapabilityError::UnsupportedCancellationMode {
1944 cancellation: policy.cancellation(),
1945 });
1946 }
1947 }
1948 for group in manifest.groups() {
1949 for requirement in group.requirements().operations() {
1950 self.validate_requirement(requirement)?;
1951 }
1952 }
1953 for route in manifest.routes() {
1954 self.validate_requirement(route.requirement())?;
1955 if let Some(boundary) = route.boundary_contract() {
1956 if !self.boundary_framing.contains(&boundary.protocol) {
1957 return Err(CommunicationCapabilityError::MissingBoundaryFraming {
1958 protocol: boundary.protocol,
1959 });
1960 }
1961 }
1962 }
1963 Ok(())
1964 }
1965
1966 fn validate_requirement(
1967 &self,
1968 requirement: &CommunicationOperationRequirement,
1969 ) -> Result<(), CommunicationCapabilityError> {
1970 let capability = self
1971 .operations
1972 .iter()
1973 .find(|capability| capability.operation() == requirement.operation())
1974 .ok_or(CommunicationCapabilityError::MissingOperation {
1975 operation: requirement.operation(),
1976 })?;
1977 for dtype in requirement.dtypes() {
1978 if !capability.dtypes().contains(dtype) {
1979 return Err(CommunicationCapabilityError::UnsupportedDtype {
1980 operation: requirement.operation(),
1981 dtype: dtype.clone(),
1982 });
1983 }
1984 }
1985 match (capability.limits(), requirement.limits()) {
1986 (Some(available), Some(required)) if available.covers(required) => {}
1987 (None, None) => {}
1988 _ => {
1989 return Err(CommunicationCapabilityError::InsufficientLimits {
1990 operation: requirement.operation(),
1991 })
1992 }
1993 }
1994 if requirement.exact_completion() && !capability.exact_completion() {
1995 return Err(CommunicationCapabilityError::MissingExactCompletion {
1996 operation: requirement.operation(),
1997 });
1998 }
1999 Ok(())
2000 }
2001}
2002
2003fn unique_axis_groups(
2004 topology: ParallelTopology,
2005 axis: ParallelAxis,
2006) -> Result<Vec<Vec<usize>>, CommunicationManifestError> {
2007 let mut seen = BTreeSet::new();
2008 let mut groups = Vec::new();
2009 for rank in 0..topology.world_size() {
2010 let members = topology
2011 .axis_members(rank, axis)
2012 .map_err(|_| CommunicationManifestError::InvalidTopologyProjection)?;
2013 if seen.insert(members.clone()) {
2014 groups.push(members);
2015 }
2016 }
2017 Ok(groups)
2018}
2019
2020fn contains_duplicate_dtypes(dtypes: &[TensorDtype]) -> bool {
2021 dtypes
2022 .iter()
2023 .enumerate()
2024 .any(|(index, dtype)| dtypes[..index].contains(dtype))
2025}
2026
2027#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
2029#[non_exhaustive]
2030pub enum CommunicationManifestError {
2031 #[error("communication boundary framing contract is invalid")]
2033 InvalidBoundaryContract,
2034 #[error("communication rank {rank} is outside world size {world_size}")]
2036 RankOutOfRange {
2037 rank: usize,
2039 world_size: usize,
2041 },
2042 #[error("rank topology does not match the topology being projected")]
2044 TopologyMismatch,
2045 #[error("parallel topology could not be projected into communication descriptors")]
2047 InvalidTopologyProjection,
2048 #[error("communication operation has invalid tensor or per-peer limits")]
2050 InvalidOperationLimits,
2051 #[error("communication operation tensor dtypes must be non-empty and unique")]
2053 InvalidOperationDtypes,
2054 #[error("communication completion policy must have a positive millisecond deadline")]
2056 InvalidCompletionPolicy,
2057 #[error("communication completion capabilities must be non-empty and unique")]
2059 InvalidCompletionCapabilities,
2060 #[error("communication group operations must be non-empty and unique")]
2062 DuplicateOrMissingOperation,
2063 #[error("communication group {id:?} has no members")]
2065 EmptyGroup {
2066 id: CollectiveGroupId,
2068 },
2069 #[error("communication group {id:?} repeats a world rank")]
2071 DuplicateGroupMember {
2072 id: CollectiveGroupId,
2074 },
2075 #[error("communication group {id:?} contains a rank outside world size {world_size}")]
2077 GroupMemberOutOfRange {
2078 id: CollectiveGroupId,
2080 world_size: usize,
2082 },
2083 #[error("communication group {id:?} has the wrong local member index")]
2085 WrongLocalIndex {
2086 id: CollectiveGroupId,
2088 },
2089 #[error("communication group ID {id:?} is repeated")]
2091 DuplicateGroupId {
2092 id: CollectiveGroupId,
2094 },
2095 #[error("communication group {id:?} has creation order {actual}, expected {expected}")]
2097 WrongGroupOrder {
2098 id: CollectiveGroupId,
2100 expected: usize,
2102 actual: usize,
2104 },
2105 #[error("communication route {id:?} must have distinct endpoints")]
2107 InvalidRouteEndpoints {
2108 id: CommunicationRouteId,
2110 },
2111 #[error("communication route {id:?} must require send/receive")]
2113 InvalidRouteOperation {
2114 id: CommunicationRouteId,
2116 },
2117 #[error("communication route {id:?} contains an endpoint outside world size {world_size}")]
2119 RouteEndpointOutOfRange {
2120 id: CommunicationRouteId,
2122 world_size: usize,
2124 },
2125 #[error("communication route ID {id:?} is repeated")]
2127 DuplicateRouteId {
2128 id: CommunicationRouteId,
2130 },
2131 #[error("communication route {id:?} has submission order {actual}, expected {expected}")]
2133 WrongRouteOrder {
2134 id: CommunicationRouteId,
2136 expected: usize,
2138 actual: usize,
2140 },
2141 #[error("communication projection has {actual} manifests, expected {expected}")]
2143 WrongManifestCount {
2144 expected: usize,
2146 actual: usize,
2148 },
2149 #[error("communication projection is missing rank {rank}")]
2151 MissingRankManifest {
2152 rank: usize,
2154 },
2155 #[error("communication projection repeats rank {rank}")]
2157 DuplicateRankManifest {
2158 rank: usize,
2160 },
2161 #[error("communication projection for rank {rank} is incompatible with its peers")]
2163 IncompatibleRankManifest {
2164 rank: usize,
2166 },
2167 #[error("communication descriptor count exceeds its stable ID representation")]
2169 DescriptorCountOverflow,
2170 #[error(
2172 "communication peer counts have send length {send} and receive length {receive}, expected {group_size}"
2173 )]
2174 InvalidPeerCounts {
2175 group_size: usize,
2177 send: usize,
2179 receive: usize,
2181 },
2182}
2183
2184#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
2186#[non_exhaustive]
2187pub enum CommunicationManifestConsensusError {
2188 #[error("communication manifest consensus topology has no participants")]
2190 EmptyTopology,
2191 #[error("communication manifest consensus {0} overflowed")]
2193 MetadataOverflow(&'static str),
2194 #[error("communication manifest encoding failed: {0}")]
2196 Encoding(String),
2197 #[error("communication manifest consensus transport failed: {0}")]
2199 Transport(String),
2200 #[error(
2202 "communication manifest {stage} gather returned {actual} words; expected {expected} for {participants} ranks"
2203 )]
2204 MalformedGather {
2205 stage: &'static str,
2207 expected: usize,
2209 actual: usize,
2211 participants: usize,
2213 },
2214 #[error("communication manifest payload length {length} from rank {rank} exceeds usize")]
2216 PayloadLengthOverflow {
2217 rank: usize,
2219 length: u64,
2221 },
2222 #[error(
2224 "communication manifest payload from rank {rank} has length {length}, but only {available} bytes were gathered"
2225 )]
2226 InvalidPayloadLength {
2227 rank: usize,
2229 length: usize,
2231 available: usize,
2233 },
2234 #[error("communication manifest payload from rank {rank} is invalid: {message}")]
2236 InvalidEncoding {
2237 rank: usize,
2239 message: String,
2241 },
2242 #[error(transparent)]
2244 Manifest(#[from] CommunicationManifestError),
2245}
2246
2247#[derive(Debug, Clone, Eq, PartialEq, thiserror::Error)]
2249#[non_exhaustive]
2250pub enum CommunicationCapabilityError {
2251 #[error("communication group {id:?} is unreachable with the selected topology mechanisms")]
2253 UnreachableGroup {
2254 id: CollectiveGroupId,
2256 },
2257 #[error(
2259 "communication route {id:?} ({source_rank} -> {destination_rank}) is unreachable with the selected topology mechanisms"
2260 )]
2261 UnreachableRoute {
2262 id: CommunicationRouteId,
2264 source_rank: usize,
2266 destination_rank: usize,
2268 },
2269 #[error("boundary framing protocol {protocol:?} is unavailable")]
2271 MissingBoundaryFraming {
2272 protocol: BoundaryFramingProtocol,
2274 },
2275 #[error("bounded communication completion is unavailable")]
2277 MissingBoundedCompletion,
2278 #[error("communication manifest has no selected bounded completion policy")]
2280 MissingSelectedCompletionPolicy,
2281 #[error("communication completion cannot apply cancellation mode {cancellation:?}")]
2283 UnsupportedCancellationMode {
2284 cancellation: CompletionCancellationMode,
2286 },
2287 #[error("communication operation {operation:?} is unavailable")]
2289 MissingOperation {
2290 operation: CommunicationOperation,
2292 },
2293 #[error("communication operation {operation:?} does not support dtype {dtype:?}")]
2295 UnsupportedDtype {
2296 operation: CommunicationOperation,
2298 dtype: TensorDtype,
2300 },
2301 #[error("communication operation {operation:?} has insufficient tensor or count limits")]
2303 InsufficientLimits {
2304 operation: CommunicationOperation,
2306 },
2307 #[error("communication operation {operation:?} lacks exact completion")]
2309 MissingExactCompletion {
2310 operation: CommunicationOperation,
2312 },
2313}
2314
2315#[cfg(test)]
2316mod tests {
2317 use super::*;
2318
2319 fn test_completion_policy() -> CommunicationCompletionPolicy {
2320 CommunicationCompletionPolicy::new(
2321 std::time::Duration::from_secs(1),
2322 CompletionCancellationMode::QuarantineUntilComplete,
2323 )
2324 .unwrap()
2325 }
2326
2327 fn test_completion_capabilities() -> CommunicationCompletionCapabilities {
2328 CommunicationCompletionCapabilities::new([
2329 CompletionCancellationMode::QuarantineUntilComplete,
2330 ])
2331 .unwrap()
2332 }
2333
2334 struct ScriptedManifestTransport {
2335 encoded: Vec<Vec<u8>>,
2336 calls: std::cell::Cell<usize>,
2337 }
2338
2339 impl ScriptedManifestTransport {
2340 fn new(manifests: &[CommunicationManifest]) -> Self {
2341 Self {
2342 encoded: manifests
2343 .iter()
2344 .map(|manifest| serde_json::to_vec(manifest).unwrap())
2345 .collect(),
2346 calls: std::cell::Cell::new(0),
2347 }
2348 }
2349 }
2350
2351 impl ConsensusTransport for ScriptedManifestTransport {
2352 type Error = std::convert::Infallible;
2353
2354 fn participant_count(&self) -> usize {
2355 self.encoded.len()
2356 }
2357
2358 fn all_gather_words(&self, local: &[u32]) -> Result<Vec<u32>, Self::Error> {
2359 let call = self.calls.get();
2360 self.calls.set(call + 1);
2361 match call {
2362 0 => {
2363 assert_eq!(local.len(), 2);
2364 Ok(self
2365 .encoded
2366 .iter()
2367 .flat_map(|payload| {
2368 let length = u64::try_from(payload.len()).unwrap();
2369 [length as u32, (length >> 32) as u32]
2370 })
2371 .collect())
2372 }
2373 1 => {
2374 let padded_words = self
2375 .encoded
2376 .iter()
2377 .map(|payload| words_for_bytes(payload.len()))
2378 .max()
2379 .unwrap();
2380 assert_eq!(local.len(), padded_words);
2381 Ok(self
2382 .encoded
2383 .iter()
2384 .flat_map(|payload| encode_manifest_words(payload, padded_words))
2385 .collect())
2386 }
2387 _ => panic!("manifest consensus performs exactly two gathers"),
2388 }
2389 }
2390 }
2391
2392 fn limits() -> CommunicationTensorLimits {
2393 CommunicationTensorLimits::new(2, 3, 4096, None).unwrap()
2394 }
2395
2396 fn requirement(operation: CommunicationOperation) -> CommunicationOperationRequirement {
2397 CommunicationOperationRequirement::tensors(
2398 operation,
2399 [TensorDtype::F32, TensorDtype::Bf16],
2400 if operation == CommunicationOperation::VariableAllToAll {
2401 CommunicationTensorLimits::new(2, 3, 4096, Some(2048)).unwrap()
2402 } else {
2403 limits()
2404 },
2405 true,
2406 )
2407 .unwrap()
2408 }
2409
2410 fn group_requirements(operation: CommunicationOperation) -> CommunicationGroupRequirements {
2411 CommunicationGroupRequirements::new([requirement(operation)]).unwrap()
2412 }
2413
2414 fn route_requirement() -> CommunicationOperationRequirement {
2415 requirement(CommunicationOperation::SendReceive)
2416 }
2417
2418 fn projection_plan() -> TopologyCommunicationPlan {
2419 TopologyCommunicationPlan::new()
2420 .with_tensor_groups(group_requirements(CommunicationOperation::AllReduceSum))
2421 .with_expert_groups(group_requirements(CommunicationOperation::VariableAllToAll))
2422 .with_data_groups(group_requirements(CommunicationOperation::AllGatherEven))
2423 .with_pipeline_routes(route_requirement())
2424 .unwrap()
2425 }
2426
2427 fn publication_requirements() -> CommunicationGroupRequirements {
2428 CommunicationGroupRequirements::new([
2429 CommunicationOperationRequirement::tensors(
2430 CommunicationOperation::Broadcast,
2431 [TensorDtype::F32],
2432 CommunicationTensorLimits::new(1, 3, 8192, None).unwrap(),
2433 true,
2434 )
2435 .unwrap(),
2436 CommunicationOperationRequirement::barrier(true),
2437 ])
2438 .unwrap()
2439 }
2440
2441 #[test]
2442 fn session_group_is_first_stable_world_group_with_exact_publication_requirements() {
2443 let topology = ParallelTopology::new(2, 2, 1, 1).unwrap();
2444 let plan = TopologyCommunicationPlan::new()
2445 .with_completion_policy(test_completion_policy())
2446 .with_session_group(publication_requirements())
2447 .with_tensor_groups(group_requirements(CommunicationOperation::AllReduceSum));
2448 let selected_id = plan.session_group_id().unwrap();
2449 let manifests = project_all_communication_manifests(topology, &plan).unwrap();
2450
2451 assert_eq!(selected_id, CollectiveGroupId::new(1));
2452 for (rank, manifest) in manifests.iter().enumerate() {
2453 let session = &manifest.groups()[0];
2454 assert_eq!(session.id(), selected_id);
2455 assert_eq!(session.creation_order(), 0);
2456 assert_eq!(session.members(), [0, 1, 2, 3]);
2457 assert_eq!(session.local_index(), Some(rank));
2458 assert_eq!(session.requirements(), &publication_requirements());
2459 assert_ne!(manifest.groups()[1].id(), selected_id);
2460 }
2461
2462 let capabilities = CommunicationCapabilities::new([
2463 requirement(CommunicationOperation::AllReduceSum),
2464 CommunicationOperationRequirement::tensors(
2465 CommunicationOperation::Broadcast,
2466 [TensorDtype::F32],
2467 CommunicationTensorLimits::new(1, 3, 8192, None).unwrap(),
2468 true,
2469 )
2470 .unwrap(),
2471 CommunicationOperationRequirement::barrier(true),
2472 ])
2473 .unwrap()
2474 .with_completion_capabilities(test_completion_capabilities());
2475 capabilities.validate_manifest(&manifests[0]).unwrap();
2476
2477 let graph =
2478 crate::ExecutionGraph::new(vec![crate::ExecutionGroupSpec::root("decoder")], "decoder")
2479 .unwrap();
2480 let execution = crate::PartitionedExecutionPlan::new(
2481 graph,
2482 vec![(crate::ArchitectureGroupKind::Decoder, false)],
2483 vec![None],
2484 Vec::new(),
2485 Some(crate::PartitionOutputPublication {
2486 group: selected_id,
2487 owner_rank: 3,
2488 }),
2489 Some(selected_id),
2490 crate::PipelineWireContract::new(crate::PipelineActivationDtype::Float32),
2491 )
2492 .unwrap();
2493 assert_eq!(execution.publication().unwrap().group, selected_id);
2494 assert_eq!(execution.commit_barrier(), Some(selected_id));
2495 }
2496
2497 #[test]
2498 fn group_and_manifest_validation_reject_membership_and_local_index_corruption() {
2499 let requirements = group_requirements(CommunicationOperation::AllReduceSum);
2500 assert_eq!(
2501 CommunicationGroupDescriptor::new(
2502 CollectiveGroupId::new(4),
2503 0,
2504 vec![0, 0],
2505 Some(0),
2506 requirements.clone(),
2507 ),
2508 Err(CommunicationManifestError::DuplicateGroupMember {
2509 id: CollectiveGroupId::new(4)
2510 })
2511 );
2512
2513 let out_of_range = CommunicationGroupDescriptor::new(
2514 CollectiveGroupId::new(4),
2515 0,
2516 vec![0, 3],
2517 Some(0),
2518 requirements.clone(),
2519 )
2520 .unwrap();
2521 assert_eq!(
2522 CommunicationManifest::new(2, 0, vec![out_of_range], vec![]),
2523 Err(CommunicationManifestError::GroupMemberOutOfRange {
2524 id: CollectiveGroupId::new(4),
2525 world_size: 2,
2526 })
2527 );
2528
2529 let wrong_local = CommunicationGroupDescriptor::new(
2530 CollectiveGroupId::new(4),
2531 0,
2532 vec![0, 1],
2533 Some(1),
2534 requirements,
2535 )
2536 .unwrap();
2537 assert_eq!(
2538 CommunicationManifest::new(2, 0, vec![wrong_local], vec![]),
2539 Err(CommunicationManifestError::WrongLocalIndex {
2540 id: CollectiveGroupId::new(4)
2541 })
2542 );
2543 }
2544
2545 #[test]
2546 fn route_and_order_validation_rejects_wrong_endpoints_and_sequences() {
2547 let route = CommunicationRouteDescriptor::new(
2548 CommunicationRouteId::new(8),
2549 0,
2550 0,
2551 3,
2552 route_requirement(),
2553 )
2554 .unwrap();
2555 assert_eq!(
2556 CommunicationManifest::new(2, 0, vec![], vec![route]),
2557 Err(CommunicationManifestError::RouteEndpointOutOfRange {
2558 id: CommunicationRouteId::new(8),
2559 world_size: 2,
2560 })
2561 );
2562
2563 let group = CommunicationGroupDescriptor::new(
2564 CollectiveGroupId::new(2),
2565 1,
2566 vec![0, 1],
2567 Some(0),
2568 group_requirements(CommunicationOperation::AllReduceSum),
2569 )
2570 .unwrap();
2571 assert_eq!(
2572 CommunicationManifest::new(2, 0, vec![group], vec![]),
2573 Err(CommunicationManifestError::WrongGroupOrder {
2574 id: CollectiveGroupId::new(2),
2575 expected: 0,
2576 actual: 1,
2577 })
2578 );
2579
2580 let route = CommunicationRouteDescriptor::new(
2581 CommunicationRouteId::new(8),
2582 1,
2583 0,
2584 1,
2585 route_requirement(),
2586 )
2587 .unwrap();
2588 assert_eq!(
2589 CommunicationManifest::new(2, 0, vec![], vec![route]),
2590 Err(CommunicationManifestError::WrongRouteOrder {
2591 id: CommunicationRouteId::new(8),
2592 expected: 0,
2593 actual: 1,
2594 })
2595 );
2596 }
2597
2598 #[test]
2599 fn cartesian_projection_is_deterministic_and_compatible_for_every_rank() {
2600 let topology = ParallelTopology::new(2, 3, 2, 2).unwrap();
2601 let manifests = project_all_communication_manifests(topology, &projection_plan()).unwrap();
2602 assert_eq!(manifests.len(), topology.world_size());
2603 assert_eq!(manifests[0].groups().len(), 3);
2604 assert_eq!(manifests[0].routes().len(), 16);
2605 assert_eq!(manifests[0].groups()[0].members(), [0, 2]);
2606 assert_eq!(manifests[0].groups()[0].local_index(), Some(0));
2607 assert_eq!(manifests[1].groups()[0].members(), [1, 3]);
2608 assert_eq!(manifests[1].groups()[0].local_index(), Some(0));
2609 assert_eq!(manifests[0].routes()[0].source(), 0);
2610 assert_eq!(manifests[0].routes()[0].destination(), 4);
2611
2612 let again = project_all_communication_manifests(topology, &projection_plan()).unwrap();
2613 assert_eq!(manifests, again);
2614 validate_compatible_communication_manifests(&manifests).unwrap();
2615 }
2616
2617 #[test]
2618 fn cross_rank_validation_detects_descriptor_disagreement() {
2619 let topology = ParallelTopology::new(2, 1, 1, 1).unwrap();
2620 let mut manifests = project_all_communication_manifests(
2621 topology,
2622 &TopologyCommunicationPlan::new()
2623 .with_completion_policy(test_completion_policy())
2624 .with_tensor_groups(group_requirements(CommunicationOperation::AllReduceSum)),
2625 )
2626 .unwrap();
2627 manifests[1].groups[0].members.swap(0, 1);
2628 manifests[1].groups[0].local_index = Some(0);
2629 assert_eq!(
2630 validate_compatible_communication_manifests(&manifests),
2631 Err(CommunicationManifestError::IncompatibleRankManifest { rank: 1 })
2632 );
2633 }
2634
2635 #[test]
2636 fn manifest_consensus_gathers_variable_payloads_and_rejects_limit_disagreement() {
2637 let topology = ParallelTopology::new(2, 1, 1, 1).unwrap();
2638 let mut manifests = project_all_communication_manifests(
2639 topology,
2640 &TopologyCommunicationPlan::new()
2641 .with_completion_policy(test_completion_policy())
2642 .with_tensor_groups(group_requirements(CommunicationOperation::AllReduceSum)),
2643 )
2644 .unwrap();
2645 let rank_one = &manifests[1].groups[0];
2646 manifests[1].groups[0] = CommunicationGroupDescriptor::new(
2647 rank_one.id(),
2648 rank_one.creation_order(),
2649 rank_one.members().to_vec(),
2650 rank_one.local_index(),
2651 CommunicationGroupRequirements::new([CommunicationOperationRequirement::tensors(
2652 CommunicationOperation::AllReduceSum,
2653 [TensorDtype::F32, TensorDtype::Bf16],
2654 CommunicationTensorLimits::new(2, 3, 32, None).unwrap(),
2655 true,
2656 )
2657 .unwrap()])
2658 .unwrap(),
2659 )
2660 .unwrap();
2661 let transport = ScriptedManifestTransport::new(&manifests);
2662
2663 assert_eq!(
2664 validate_communication_manifest_consensus(&transport, &manifests[0]),
2665 Err(CommunicationManifestConsensusError::Manifest(
2666 CommunicationManifestError::IncompatibleRankManifest { rank: 1 }
2667 ))
2668 );
2669 assert_eq!(transport.calls.get(), 2);
2670 assert_ne!(transport.encoded[0].len(), transport.encoded[1].len());
2671 }
2672
2673 #[test]
2674 fn manifest_consensus_accepts_complete_compatible_rank_artifacts() {
2675 let manifests = project_all_communication_manifests(
2676 ParallelTopology::new(2, 1, 1, 1).unwrap(),
2677 &TopologyCommunicationPlan::new()
2678 .with_tensor_groups(group_requirements(CommunicationOperation::AllReduceSum)),
2679 )
2680 .unwrap();
2681 let transport = ScriptedManifestTransport::new(&manifests);
2682
2683 validate_communication_manifest_consensus(&transport, &manifests[0]).unwrap();
2684 assert_eq!(transport.calls.get(), 2);
2685 }
2686
2687 #[test]
2688 fn manifest_consensus_defers_world_validation_until_after_both_gathers() {
2689 let manifests = vec![
2690 CommunicationManifest::new(2, 0, Vec::new(), Vec::new()).unwrap(),
2691 CommunicationManifest::new(3, 1, Vec::new(), Vec::new()).unwrap(),
2692 ];
2693 let transport = ScriptedManifestTransport::new(&manifests);
2694
2695 assert_eq!(
2696 validate_communication_manifest_consensus(&transport, &manifests[0]),
2697 Err(CommunicationManifestConsensusError::Manifest(
2698 CommunicationManifestError::IncompatibleRankManifest { rank: 1 }
2699 ))
2700 );
2701 assert_eq!(transport.calls.get(), 2);
2702 }
2703
2704 #[test]
2705 fn capability_validation_is_fine_grained_and_fail_closed() {
2706 let topology = ParallelTopology::new(2, 1, 1, 1).unwrap();
2707 let manifest = project_all_communication_manifests(
2708 topology,
2709 &TopologyCommunicationPlan::new()
2710 .with_completion_policy(test_completion_policy())
2711 .with_tensor_groups(group_requirements(CommunicationOperation::AllReduceSum)),
2712 )
2713 .unwrap()
2714 .remove(0);
2715
2716 let missing = CommunicationCapabilities::new([])
2717 .unwrap()
2718 .with_completion_capabilities(test_completion_capabilities());
2719 assert_eq!(
2720 missing.validate_manifest(&manifest),
2721 Err(CommunicationCapabilityError::MissingOperation {
2722 operation: CommunicationOperation::AllReduceSum,
2723 })
2724 );
2725
2726 let narrow = CommunicationCapabilities::new([CommunicationOperationRequirement::tensors(
2727 CommunicationOperation::AllReduceSum,
2728 [TensorDtype::F32],
2729 CommunicationTensorLimits::new(1, 2, 32, None).unwrap(),
2730 false,
2731 )
2732 .unwrap()])
2733 .unwrap()
2734 .with_completion_capabilities(test_completion_capabilities());
2735 assert_eq!(
2736 narrow.validate_manifest(&manifest),
2737 Err(CommunicationCapabilityError::UnsupportedDtype {
2738 operation: CommunicationOperation::AllReduceSum,
2739 dtype: TensorDtype::Bf16,
2740 })
2741 );
2742 }
2743
2744 #[test]
2745 fn capability_validation_covers_gather_result_size_separately() {
2746 let required = CommunicationOperationRequirement::tensors(
2747 CommunicationOperation::AllGatherUneven,
2748 [TensorDtype::F32],
2749 CommunicationTensorLimits::new(1, 3, 32, None)
2750 .unwrap()
2751 .with_output_tensor_elements(64)
2752 .unwrap(),
2753 true,
2754 )
2755 .unwrap();
2756 let available =
2757 CommunicationCapabilities::new([CommunicationOperationRequirement::tensors(
2758 CommunicationOperation::AllGatherUneven,
2759 [TensorDtype::F32],
2760 CommunicationTensorLimits::new(1, 3, 64, None).unwrap(),
2761 true,
2762 )
2763 .unwrap()])
2764 .unwrap();
2765 assert!(available.validate_requirement(&required).is_ok());
2766
2767 let insufficient =
2768 CommunicationCapabilities::new([CommunicationOperationRequirement::tensors(
2769 CommunicationOperation::AllGatherUneven,
2770 [TensorDtype::F32],
2771 CommunicationTensorLimits::new(1, 3, 32, None).unwrap(),
2772 true,
2773 )
2774 .unwrap()])
2775 .unwrap();
2776 assert_eq!(
2777 insufficient.validate_requirement(&required),
2778 Err(CommunicationCapabilityError::InsufficientLimits {
2779 operation: CommunicationOperation::AllGatherUneven,
2780 })
2781 );
2782 }
2783
2784 #[test]
2785 fn variable_peer_counts_preserve_zeroes_and_exact_member_order() {
2786 let counts = CommunicationPeerCounts::new(vec![0, 3, 1], vec![2, 0, 2], 3).unwrap();
2787 assert_eq!(counts.send(), [0, 3, 1]);
2788 assert_eq!(counts.receive(), [2, 0, 2]);
2789 assert_eq!(counts.group_size(), 3);
2790 assert_eq!(
2791 CommunicationPeerCounts::new(vec![1], vec![1, 0], 2),
2792 Err(CommunicationManifestError::InvalidPeerCounts {
2793 group_size: 2,
2794 send: 1,
2795 receive: 2,
2796 })
2797 );
2798 }
2799
2800 #[test]
2801 fn failure_agreement_is_payload_free_and_not_covered_by_a_barrier() {
2802 let required = CommunicationOperationRequirement::failure_agreement(true);
2803 assert_eq!(
2804 required.operation(),
2805 CommunicationOperation::FailureAgreement
2806 );
2807 assert!(required.dtypes().is_empty());
2808 assert_eq!(required.limits(), None);
2809
2810 let barrier_only =
2811 CommunicationCapabilities::new([CommunicationOperationRequirement::barrier(true)])
2812 .unwrap();
2813 assert_eq!(
2814 barrier_only.validate_requirement(&required),
2815 Err(CommunicationCapabilityError::MissingOperation {
2816 operation: CommunicationOperation::FailureAgreement,
2817 })
2818 );
2819 }
2820
2821 #[test]
2822 fn completion_policy_deserialization_revalidates_positive_deadline() {
2823 assert!(
2824 serde_json::from_value::<CommunicationCompletionPolicy>(serde_json::json!({
2825 "timeout_millis": 0,
2826 "cancellation": "quarantine_until_complete"
2827 }))
2828 .is_err()
2829 );
2830 }
2831
2832 #[test]
2833 fn communication_resources_require_selected_supported_completion() {
2834 let group = CommunicationGroupDescriptor::new(
2835 CollectiveGroupId::new(1),
2836 0,
2837 vec![0],
2838 Some(0),
2839 CommunicationGroupRequirements::new([CommunicationOperationRequirement::barrier(true)])
2840 .unwrap(),
2841 )
2842 .unwrap();
2843 let manifest = CommunicationManifest::new(1, 0, vec![group], Vec::new()).unwrap();
2844 let capabilities =
2845 CommunicationCapabilities::new([CommunicationOperationRequirement::barrier(true)])
2846 .unwrap()
2847 .with_completion_capabilities(
2848 CommunicationCompletionCapabilities::new([
2849 CompletionCancellationMode::QuarantineUntilComplete,
2850 ])
2851 .unwrap(),
2852 );
2853 assert_eq!(
2854 capabilities.validate_manifest(&manifest),
2855 Err(CommunicationCapabilityError::MissingSelectedCompletionPolicy)
2856 );
2857 let manifest = manifest.with_completion_policy(
2858 CommunicationCompletionPolicy::new(
2859 std::time::Duration::from_secs(1),
2860 CompletionCancellationMode::QuarantineUntilComplete,
2861 )
2862 .unwrap(),
2863 );
2864 capabilities.validate_manifest(&manifest).unwrap();
2865 }
2866
2867 #[test]
2868 fn role_exact_frames_use_actual_variable_dimensions_and_reject_role_or_fixed_drift() {
2869 let admitted = RoleExactBoundaryContract::new(
2870 "nemotron_h.target",
2871 [
2872 BoundaryRoleContract::symbolic(
2873 "hidden",
2874 TensorDtype::F32,
2875 vec![
2876 BoundaryDimensionContract::Variable { maximum: 4 },
2877 BoundaryDimensionContract::Variable { maximum: 16 },
2878 BoundaryDimensionContract::Fixed(12),
2879 ],
2880 )
2881 .unwrap(),
2882 BoundaryRoleContract::symbolic(
2883 "embedded",
2884 TensorDtype::F32,
2885 vec![
2886 BoundaryDimensionContract::Variable { maximum: 4 },
2887 BoundaryDimensionContract::Variable { maximum: 16 },
2888 BoundaryDimensionContract::Fixed(12),
2889 ],
2890 )
2891 .unwrap(),
2892 ],
2893 )
2894 .unwrap();
2895 let actual = vec![
2896 BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![1, 3, 12]).unwrap(),
2897 BoundaryRoleContract::new("embedded", TensorDtype::F32, vec![1, 3, 12]).unwrap(),
2898 ];
2899 let framed = admitted
2900 .frame_values(CommunicationRouteId::new(7), &actual, vec![1_u8, 2])
2901 .unwrap();
2902 assert_ne!(framed[0].header(), framed[1].header());
2903
2904 let swapped = vec![actual[1].clone(), actual[0].clone()];
2905 assert_eq!(
2906 admitted.frame_values(CommunicationRouteId::new(7), &swapped, vec![1_u8, 2]),
2907 Err(CommunicationManifestError::InvalidBoundaryContract)
2908 );
2909 let fixed_shrink = vec![
2910 BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![1, 3, 11]).unwrap(),
2911 actual[1].clone(),
2912 ];
2913 assert_eq!(
2914 admitted.frame_values(CommunicationRouteId::new(7), &fixed_shrink, vec![1_u8, 2],),
2915 Err(CommunicationManifestError::InvalidBoundaryContract)
2916 );
2917 }
2918
2919 #[test]
2920 fn role_exact_framing_capability_and_byte_overflow_fail_before_submission() {
2921 let requirement = CommunicationOperationRequirement::tensors(
2922 CommunicationOperation::SendReceive,
2923 [TensorDtype::F32],
2924 CommunicationTensorLimits::new(1, 3, 4096, None).unwrap(),
2925 true,
2926 )
2927 .unwrap();
2928 let role = BoundaryRoleContract::symbolic(
2929 "hidden",
2930 TensorDtype::F32,
2931 vec![BoundaryDimensionContract::Fixed(1)],
2932 )
2933 .unwrap();
2934 let route = CommunicationRouteDescriptor::new(
2935 CommunicationRouteId::new(3),
2936 0,
2937 0,
2938 1,
2939 requirement.clone(),
2940 )
2941 .unwrap()
2942 .with_boundary_contract(RoleExactBoundaryContract::new("none", [role]).unwrap())
2943 .unwrap();
2944 let manifest = CommunicationManifest::new(2, 0, Vec::new(), vec![route])
2945 .unwrap()
2946 .with_completion_policy(
2947 CommunicationCompletionPolicy::new(
2948 std::time::Duration::from_secs(1),
2949 CompletionCancellationMode::QuarantineUntilComplete,
2950 )
2951 .unwrap(),
2952 );
2953 let capability = CommunicationCapabilities::new([requirement.clone()])
2954 .unwrap()
2955 .with_completion_capabilities(
2956 CommunicationCompletionCapabilities::new([
2957 CompletionCancellationMode::QuarantineUntilComplete,
2958 ])
2959 .unwrap(),
2960 );
2961 assert!(matches!(
2962 capability.validate_manifest(&manifest),
2963 Err(CommunicationCapabilityError::MissingBoundaryFraming {
2964 protocol: BoundaryFramingProtocol::RoleExactV1,
2965 })
2966 ));
2967
2968 for invalid in [
2969 BoundaryRoleContract::new("hidden", TensorDtype::I32, vec![1]).unwrap(),
2970 BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![1, 1, 1, 1]).unwrap(),
2971 BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![4097]).unwrap(),
2972 ] {
2973 assert_eq!(
2974 CommunicationRouteDescriptor::new(
2975 CommunicationRouteId::new(30),
2976 0,
2977 0,
2978 1,
2979 requirement.clone(),
2980 )
2981 .unwrap()
2982 .with_boundary_contract(
2983 RoleExactBoundaryContract::new("invalid", [invalid]).unwrap(),
2984 ),
2985 Err(CommunicationManifestError::InvalidBoundaryContract),
2986 );
2987 }
2988 let inexact = CommunicationOperationRequirement::tensors(
2989 CommunicationOperation::SendReceive,
2990 [TensorDtype::F32],
2991 CommunicationTensorLimits::new(1, 3, 4096, None).unwrap(),
2992 false,
2993 )
2994 .unwrap();
2995 assert_eq!(
2996 CommunicationRouteDescriptor::new(CommunicationRouteId::new(31), 0, 0, 1, inexact,)
2997 .unwrap()
2998 .with_boundary_contract(
2999 RoleExactBoundaryContract::new(
3000 "inexact",
3001 [BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![1]).unwrap()],
3002 )
3003 .unwrap(),
3004 ),
3005 Err(CommunicationManifestError::InvalidBoundaryContract),
3006 );
3007
3008 let exact = RoleExactBoundaryContract::new(
3009 "overflow",
3010 [BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![usize::MAX, 2]).unwrap()],
3011 )
3012 .unwrap();
3013 assert_eq!(
3014 exact.frame_values(CommunicationRouteId::new(4), exact.roles(), vec![0_u8],),
3015 Err(CommunicationManifestError::InvalidBoundaryContract)
3016 );
3017 }
3018
3019 #[test]
3020 fn role_exact_contract_deserialization_revalidates_roles_dimensions_and_dtypes() {
3021 let contract = RoleExactBoundaryContract::new(
3022 "fixture",
3023 [BoundaryRoleContract::symbolic(
3024 "hidden",
3025 TensorDtype::F32,
3026 vec![BoundaryDimensionContract::Fixed(4)],
3027 )
3028 .unwrap()],
3029 )
3030 .unwrap();
3031 let valid = serde_json::to_value(&contract).unwrap();
3032
3033 let mut empty_role = valid.clone();
3034 empty_role["roles"][0]["role"] = serde_json::json!("");
3035 assert!(serde_json::from_value::<RoleExactBoundaryContract>(empty_role).is_err());
3036
3037 let mut duplicate_role = valid.clone();
3038 let repeated = duplicate_role["roles"][0].clone();
3039 duplicate_role["roles"]
3040 .as_array_mut()
3041 .unwrap()
3042 .push(repeated);
3043 assert!(serde_json::from_value::<RoleExactBoundaryContract>(duplicate_role).is_err());
3044
3045 let mut zero_dimension = valid.clone();
3046 zero_dimension["roles"][0]["shape"][0] = serde_json::json!({ "fixed": 0 });
3047 assert!(serde_json::from_value::<RoleExactBoundaryContract>(zero_dimension).is_err());
3048
3049 let mut encoded_dtype = valid;
3050 encoded_dtype["roles"][0]["dtype"] = serde_json::json!({ "encoded": "q4" });
3051 assert!(serde_json::from_value::<RoleExactBoundaryContract>(encoded_dtype).is_err());
3052 }
3053
3054 #[test]
3055 fn route_submission_waves_require_complete_disjoint_world_batches() {
3056 let requirement = CommunicationOperationRequirement::tensors(
3057 CommunicationOperation::SendReceive,
3058 [TensorDtype::F32],
3059 CommunicationTensorLimits::new(1, 3, 64, None).unwrap(),
3060 true,
3061 )
3062 .unwrap();
3063 let boundary = RoleExactBoundaryContract::new(
3064 "hidden-v1",
3065 [BoundaryRoleContract::new("hidden", TensorDtype::F32, vec![1, 2, 4]).unwrap()],
3066 )
3067 .unwrap();
3068 let route = |order: usize, source: usize, destination: usize| {
3069 CommunicationRouteDescriptor::new(
3070 CommunicationRouteId::new(order as u64),
3071 order,
3072 source,
3073 destination,
3074 requirement.clone(),
3075 )
3076 .unwrap()
3077 .with_boundary_contract(boundary.clone())
3078 .unwrap()
3079 };
3080
3081 let complete = CommunicationManifest::new(
3082 8,
3083 0,
3084 Vec::new(),
3085 (0..4).map(|rank| route(rank, rank + 4, rank)).collect(),
3086 )
3087 .unwrap();
3088 assert_eq!(complete.route_submission_waves().len(), 1);
3089 assert_eq!(complete.route_submission_waves()[0], 0..4);
3090
3091 let omitted = CommunicationManifest::new(
3092 8,
3093 0,
3094 Vec::new(),
3095 (0..3).map(|rank| route(rank, rank + 4, rank)).collect(),
3096 )
3097 .unwrap();
3098 assert_eq!(omitted.route_submission_waves(), [0..1, 1..2, 2..3]);
3099
3100 let overlapping = CommunicationManifest::new(
3101 8,
3102 0,
3103 Vec::new(),
3104 vec![
3105 route(0, 4, 0),
3106 route(1, 4, 1),
3107 route(2, 6, 2),
3108 route(3, 7, 3),
3109 ],
3110 )
3111 .unwrap();
3112 assert_eq!(
3113 overlapping.route_submission_waves(),
3114 [0..1, 1..2, 2..3, 3..4]
3115 );
3116 }
3117
3118 fn route_only_capabilities(
3119 requirement: CommunicationOperationRequirement,
3120 ) -> CommunicationCapabilities {
3121 CommunicationCapabilities::new([requirement])
3122 .unwrap()
3123 .with_completion_capabilities(test_completion_capabilities())
3124 }
3125
3126 #[test]
3127 fn prepared_realization_rejects_unreachable_ring_routes_before_callbacks() {
3128 let requirement = CommunicationOperationRequirement::tensors(
3129 CommunicationOperation::SendReceive,
3130 [TensorDtype::F32],
3131 CommunicationTensorLimits::new(1, 3, 64, None).unwrap(),
3132 true,
3133 )
3134 .unwrap();
3135 let plan = TopologyCommunicationPlan::new()
3136 .with_completion_policy(test_completion_policy())
3137 .with_pipeline_routes(requirement.clone())
3138 .unwrap();
3139 let topology = ParallelTopology::new(2, 3, 1, 1).unwrap();
3140 let manifests = project_all_communication_manifests(topology, &plan).unwrap();
3141 let error = prepare_communication_realization(
3142 &manifests[0],
3143 &manifests,
3144 &route_only_capabilities(requirement),
3145 CommunicationTopologyCapabilities::RingWithWorldWaves,
3146 )
3147 .unwrap_err();
3148 assert!(matches!(
3149 error,
3150 CommunicationRealizationError::Capability(
3151 CommunicationCapabilityError::UnreachableRoute { .. }
3152 )
3153 ));
3154 }
3155
3156 #[test]
3157 fn prepared_realization_proves_world_waves_before_mechanism_callbacks() {
3158 let requirement = CommunicationOperationRequirement::tensors(
3159 CommunicationOperation::SendReceive,
3160 [TensorDtype::F32],
3161 CommunicationTensorLimits::new(1, 3, 64, None).unwrap(),
3162 true,
3163 )
3164 .unwrap();
3165 let plan = TopologyCommunicationPlan::new()
3166 .with_completion_policy(test_completion_policy())
3167 .with_pipeline_routes(requirement.clone())
3168 .unwrap();
3169 let topology = ParallelTopology::new(2, 2, 1, 1).unwrap();
3170 let manifests = project_all_communication_manifests(topology, &plan).unwrap();
3171 let prepared = prepare_communication_realization(
3172 &manifests[0],
3173 &manifests,
3174 &route_only_capabilities(requirement),
3175 CommunicationTopologyCapabilities::RingWithWorldWaves,
3176 )
3177 .unwrap();
3178 assert!(prepared
3179 .manifest()
3180 .routes()
3181 .iter()
3182 .enumerate()
3183 .all(|(order, _)| prepared.route_world_wave(order) == Some(true)));
3184
3185 let calls = std::cell::Cell::new(0usize);
3186 let routes = prepared
3187 .try_create_routes(|descriptor, world_wave| {
3188 calls.set(calls.get() + 1);
3189 assert!(world_wave);
3190 Ok::<_, std::convert::Infallible>(descriptor.id())
3191 })
3192 .unwrap();
3193 assert_eq!(calls.get(), prepared.manifest().routes().len());
3194 assert_eq!(routes.len(), calls.get());
3195 }
3196}