2121import re
2222import subprocess
2323import tempfile
24- from typing import List
2524import logging
2625
2726from airflow import models
@@ -50,7 +49,6 @@ def __init__(self, target_rate: float = 0.1):
5049 self .frames = []
5150 self .update_events = []
5251
53- # Pre-compile regex patterns for optimized performance
5452 self ._frame_start_re = re .compile (r"\[(\d{2}:\d{2}:\d{2}\.\d{3})\].*?\[H" )
5553 self ._chips_re = re .compile (
5654 r"│\s+(/dev/vfio/\d+)\s+│.*?│\s+\d+\s+│\s+(\d+)\s+│"
@@ -104,7 +102,7 @@ def parse_log(self, log_content: str):
104102 if current_frame ["ts" ]:
105103 self .frames .append (current_frame )
106104 current_frame = self ._init_empty_frame ()
107- current_frame ["ts" ] = datetime .strptime (
105+ current_frame ["ts" ] = datetime .datetime . strptime (
108106 fs_match .group (1 ), "%H:%M:%S.%f"
109107 )
110108 continue
@@ -120,7 +118,6 @@ def filter_update_events(self):
120118 self .update_events = []
121119 last_snapshot = None
122120 for f in self .frames :
123- # Create a snapshot excluding the timestamp for comparison
124121 snapshot = {k : v for k , v in f .items () if k != "ts" }
125122 if last_snapshot is None or snapshot != last_snapshot :
126123 self .update_events .append (f )
@@ -223,7 +220,7 @@ def execute_tpu_info_cli_command(info, pod_name: str, tpu_args: str) -> str:
223220
224221
225222def verify_output_contains_patterns (
226- output : str , patterns : List [str ], context : str
223+ output : str , patterns : list [str ], context : str
227224):
228225 """Verifies that expected strings exist in the output."""
229226 for pattern in patterns :
@@ -233,36 +230,18 @@ def verify_output_contains_patterns(
233230 )
234231
235232
236- @task
237- def validate_streaming_rate (info , pod_name : str , rate : float ) -> str :
238- """
239- Executes tpu-info --streaming and validates frequency using UI and Data metrics.
240- """
241- duration = 15
242-
243- tpu_args = (
244- f"sh -c \" script -q -c 'timeout { duration } s "
245- f"tpu-info --streaming --rate { rate } ' /dev/null\" "
246- f"|| [ $? -eq 124 ]"
247- )
248- output = execute_tpu_info_cli_command (info , pod_name , tpu_args )
249-
250- patterns = ["Refresh rate:" , f"{ rate } s" ]
251- verify_output_contains_patterns (
252- output , patterns , f"Content check on { pod_name } "
253- )
254- return f"Validated { pod_name } at { rate } s"
255-
256-
257233@task
258234def validate_streaming_rate_iterations (
259- info , pod_name : str , rate : float , iteration_count : int = 40
235+ info ,
236+ pod_name : str ,
237+ rate : float ,
238+ iteration_count : int = 40 ,
239+ duration : int = 30 ,
260240) -> str :
261241 """
262242 Performs 40 iterations of 30s tests.
263243 The task succeeds if at least 50% of the iterations are valid.
264244 """
265- duration = 30
266245 analyzer = TPUPerformanceAnalyzer (target_rate = rate )
267246 success_count = 0
268247 pass_threshold = iteration_count / 2 # 50% threshold
@@ -286,14 +265,14 @@ def validate_streaming_rate_iterations(
286265 logging .info (analyzer .generate_report ())
287266 if analyzer .validate_rate_match ():
288267 success_count += 1
268+ logging .info (f"Iteration { i } : Passed validation." )
289269 else :
290270 logging .info (
291271 f"Iteration { i } : Failed validation (Intervals out of range)."
292272 )
293273 except Exception as e :
294274 logging .error (f"Iteration { i } : Command execution error: { str (e )} " )
295275
296- # Evaluation logic: Pass if success_count >= 20
297276 status_msg = f"Pod { pod_name } at { rate } s: { success_count } /{ iteration_count } iterations passed."
298277 logging .info (status_msg )
299278
@@ -376,7 +355,9 @@ def generate_second_node_pool_name(
376355 tpu_topology = config .tpu_topology ,
377356 )
378357
379- cluster_info_2 = node_pool .copy_node_pool_info_with_override (
358+ cluster_info_2 = node_pool .copy_node_pool_info_with_override .override (
359+ task_id = "copy_node_pool_info_with_override"
360+ )(
380361 info = cluster_info ,
381362 node_pool_name = generate_second_node_pool_name (cluster_info ),
382363 )
@@ -414,26 +395,32 @@ def generate_second_node_pool_name(
414395 task_id = "wait_for_job_start"
415396 )(cluster_info , pod_name_list = pod_names , job_apply_time = apply_time )
416397
417- test_rates = [0.1 , 0.5 , 1.0 , 5.0 ]
418- rate_test_groups = []
419- for rate in test_rates :
420- formatted_rate = str (rate ).replace ("." , "_" )
421-
422- with TaskGroup (
423- group_id = f"verification_group_rate_{ formatted_rate } "
424- ) as rate_group :
425- # Fix: Ensure parameters match the task signature exactly
426- validate_streaming_rate_iterations .override (
427- task_id = "streaming_rate_test" ,
428- execution_timeout = datetime .timedelta (minutes = 60 ),
429- ).partial (
430- info = cluster_info ,
431- rate = rate ,
432- iteration_count = 40 , # Pass integer directly to partial
433- ).expand (
434- pod_name = pod_names
435- )
436- rate_test_groups .append (rate_group )
398+ # Keyword arguments are generated dynamically at runtime (pylint does not
399+ # know this signature).
400+ with TaskGroup ( # pylint: disable=unexpected-keyword-arg
401+ group_id = "tpu_streaming_rate_verification"
402+ ) as rate_verification_group :
403+ test_rates = [0.1 , 0.5 , 1.0 , 5.0 ]
404+
405+ for rate in test_rates :
406+ formatted_rate = str (rate ).replace ("." , "_" )
407+
408+ # Keyword arguments are generated dynamically at runtime (pylint does not
409+ # know this signature).
410+ with TaskGroup ( # pylint: disable=unexpected-keyword-arg
411+ group_id = f"rate_{ formatted_rate } "
412+ ) as rate_iterations_group :
413+ validate_streaming_rate_iterations .override (
414+ task_id = "streaming_rate_test" ,
415+ execution_timeout = datetime .timedelta (minutes = 60 ),
416+ duration = 30 , # Each iteration runs for 30 seconds
417+ ).partial (
418+ info = cluster_info ,
419+ rate = rate ,
420+ iteration_count = 40 ,
421+ ).expand (
422+ pod_name = pod_names
423+ )
437424
438425 cleanup_workload = jobset .end_workload .override (
439426 task_id = "cleanup_workload" , trigger_rule = TriggerRule .ALL_DONE
@@ -474,7 +461,7 @@ def generate_second_node_pool_name(
474461 >> apply_time
475462 >> pod_names
476463 >> wait_for_job_start
477- >> rate_test_groups
464+ >> rate_verification_group
478465 >> cleanup_workload
479466 >> cleanup_node_pool
480467 )
0 commit comments