Skip to content

Commit f614f56

Browse files
authored
Merge pull request #172 from sbak5/sbak/fr_attr_pr_squashed
feat: Flight recorder attribution module
2 parents 3850483 + a7909b1 commit f614f56

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1878
-0
lines changed

src/nvidia_resiliency_ext/attribution/trace_analyzer/fr_attribution.py

Lines changed: 985 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 41 additions & 0 deletions
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
"""
2+
Utility functions for FR attribution test comparison and validation.
3+
"""
4+
5+
import re
6+
from typing import Any, Dict, Set
7+
8+
9+
class FRAttributionOutputParser:
10+
"""Parser for FR attribution output to extract key information for comparison."""
11+
12+
def __init__(self):
13+
self.missing_ranks_pattern = r'(\d+)\s+\|\s+([^|]+)\s+\|\s+([^|]+)\s+\|\s+([^|]+)\s+\|\s+([^|]+)\s+\|\s+([^|]+?)(?:\s|$)'
14+
self.processed_files_pattern = r'Successfully processed (\d+) files'
15+
self.group_types_pattern = r'Found group types: ([^\n]+)'
16+
17+
def parse_output(self, output: str) -> Dict[str, Any]:
18+
"""
19+
Parse FR attribution output and extract key information.
20+
21+
Args:
22+
output: The output string from fr_attribution
23+
24+
Returns:
25+
Dictionary containing parsed information
26+
"""
27+
result = {
28+
'processed_files': 0,
29+
'group_types': [],
30+
'missing_ranks_by_pg': {},
31+
'process_groups': [],
32+
'scheduling_order': {},
33+
'raw_output': output,
34+
}
35+
36+
# Extract processed files count
37+
processed_match = re.search(self.processed_files_pattern, output)
38+
if processed_match:
39+
result['processed_files'] = int(processed_match.group(1))
40+
41+
# Extract group types
42+
group_types_match = re.search(self.group_types_pattern, output)
43+
if group_types_match:
44+
group_types_str = group_types_match.group(1)
45+
result['group_types'] = [gt.strip() for gt in group_types_str.split(',')]
46+
47+
# Extract missing ranks information
48+
missing_ranks_matches = re.findall(self.missing_ranks_pattern, output)
49+
for match in missing_ranks_matches:
50+
pg_id = match[0].strip()
51+
pg_desc = match[1].strip()
52+
op_type = match[2].strip()
53+
size = match[3].strip()
54+
dtype = match[4].strip()
55+
missing_ranks_str = match[5].strip()
56+
57+
if missing_ranks_str and missing_ranks_str.strip() != '':
58+
# Clean up the missing ranks string and extract only numeric values
59+
missing_ranks_str = missing_ranks_str.strip()
60+
# Split by comma and extract only numeric values
61+
missing_ranks = []
62+
for rank in missing_ranks_str.split(','):
63+
rank = rank.strip()
64+
# Extract only the numeric part (in case there's extra text)
65+
numeric_match = re.search(r'\d+', rank)
66+
if numeric_match:
67+
missing_ranks.append(int(numeric_match.group()))
68+
69+
if missing_ranks: # Only add if we found valid ranks
70+
result['missing_ranks_by_pg'][pg_id] = {
71+
'pg_desc': pg_desc,
72+
'op_type': op_type,
73+
'size': size,
74+
'dtype': dtype,
75+
'missing_ranks': missing_ranks,
76+
}
77+
result['process_groups'].append(
78+
{
79+
'pg_id': pg_id,
80+
'pg_desc': pg_desc,
81+
'op_type': op_type,
82+
'size': size,
83+
'dtype': dtype,
84+
'missing_ranks': missing_ranks,
85+
}
86+
)
87+
88+
# Extract scheduling order
89+
scheduling_order_match = re.search(r'Using scheduling order: ({[^}]+})', output)
90+
if scheduling_order_match:
91+
import ast
92+
93+
result['scheduling_order'] = ast.literal_eval(scheduling_order_match.group(1))
94+
95+
return result
96+
97+
def extract_missing_ranks_set(self, output: str) -> Set[int]:
98+
"""
99+
Extract all missing ranks as a set from the output.
100+
101+
Args:
102+
output: The output string from fr_attribution
103+
104+
Returns:
105+
Set of missing rank numbers
106+
"""
107+
missing_ranks = set()
108+
missing_ranks_matches = re.findall(self.missing_ranks_pattern, output)
109+
110+
for match in missing_ranks_matches:
111+
missing_ranks_str = match[5].strip()
112+
if missing_ranks_str and missing_ranks_str.strip() != '':
113+
# Clean up the missing ranks string and extract only numeric values
114+
missing_ranks_str = missing_ranks_str.strip()
115+
# Split by comma and extract only numeric values
116+
for rank in missing_ranks_str.split(','):
117+
rank = rank.strip()
118+
# Extract only the numeric part (in case there's extra text)
119+
numeric_match = re.search(r'\d+', rank)
120+
if numeric_match:
121+
missing_ranks.add(int(numeric_match.group()))
122+
123+
return missing_ranks
4.5 KB
Binary file not shown.
4.51 KB
Binary file not shown.
4.32 KB
Binary file not shown.
4.32 KB
Binary file not shown.
5.37 KB
Binary file not shown.
4 KB
Binary file not shown.
7.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)