diff --git a/.gitignore b/.gitignore
index dde2a6782..787b0d487 100644
--- a/.gitignore
+++ b/.gitignore
@@ -163,5 +163,4 @@ tests/tmp/*
*wandb_storage*
.coverage/*
*.pbin
-
tutorials/profiling/experiments
\ No newline at end of file
diff --git a/src/modalities/__main__.py b/src/modalities/__main__.py
index f39073731..691369327 100644
--- a/src/modalities/__main__.py
+++ b/src/modalities/__main__.py
@@ -1,19 +1,14 @@
#!/usr/bin/env python
import json
-import logging
-import os
-import shutil
-from datetime import datetime
from functools import partial
from pathlib import Path
-from typing import Callable, Optional, Type
+from typing import Optional
import click
import click_pathlib
-import yaml
from omegaconf import DictConfig
-from pydantic import BaseModel, FilePath
+from pydantic import FilePath
from modalities.api import (
FileExistencePolicy,
@@ -27,22 +22,12 @@
shuffle_jsonl_data,
shuffle_tokenized_data,
)
-from modalities.batch import EvaluationResultBatch
-from modalities.config.component_factory import ComponentFactory
from modalities.config.config import ProcessGroupBackendType, load_app_config_dict
-from modalities.config.instantiation_models import TrainingComponentsInstantiationModel, TrainingReportGenerator
-from modalities.evaluator import Evaluator
-from modalities.gym import Gym
-from modalities.logging_broker.message_broker import MessageBroker
-from modalities.logging_broker.messages import MessageTypes, ProgressUpdate
-from modalities.logging_broker.publisher import MessagePublisher
-from modalities.logging_broker.subscriber import MessageSubscriberIF
+from modalities.config.instantiation_models import TrainingComponentsInstantiationModel
+from modalities.main import Main
from modalities.models.huggingface_adapters.hf_adapter import HFModelAdapter
-from modalities.registry.components import COMPONENTS
-from modalities.registry.registry import Registry
from modalities.running_env.cuda_env import CudaEnv
-from modalities.trainer import Trainer
-from modalities.util import get_experiment_id_of_run, get_total_number_of_trainable_parameters, print_rank_0
+from modalities.utils.profilers.modalities_profiler import ModalitiesProfiler
@click.group()
@@ -511,194 +496,54 @@ def CMD_shuffle_jsonl_data(
)
-class Main:
- """Main class that orchestrates the training process."""
-
- def __init__(
- self,
- config_path: Path,
- additional_resolver_funs: Optional[dict[str, Callable]] = None,
- experiment_id: Optional[str] = None,
- ) -> None:
- if experiment_id is None:
- experiment_id = get_experiment_id_of_run(config_path)
-
- self.config_dict = load_app_config_dict(
- config_file_path=config_path, experiment_id=experiment_id, additional_resolver_funs=additional_resolver_funs
- )
- self.config_path = config_path
-
- self.registry = Registry(COMPONENTS)
- self.component_factory = ComponentFactory(registry=self.registry)
-
- def add_custom_component(
- self, component_key: str, variant_key: str, custom_component: Type, custom_config: Type
- ) -> None:
- """Add a custom component to the registry.
-
- This method comes in especially handy
- when Modalities is used as a library and the user wants to add custom components
- (e.g., custom model or custom loss function) to the registry.
-
- Args:
- component_key (str): Key of the component to be added to the registry
- variant_key (str): Key of the variant to be added to the registry
- custom_component (Type): The class type of the custom component
- custom_config (Type): The pydantic config type of the custom component
- """
- self.registry.add_entity(
- component_key=component_key,
- variant_key=variant_key,
- component_type=custom_component,
- component_config_type=custom_config,
- )
-
- def build_components(self, components_model_type: Type[BaseModel]) -> BaseModel:
- """Given a pydantic basemodel, this method builds the components specified in the config file.
-
- Depending on the use case (e.g., training, inference, etc.), the user can pass different pydantic base models.
- For instance, for tokenization, the basemodel would only have the tokenization-related components specified.
-
- Args:
- components_model_type (Type[BaseModel]): The pydantic basemodel type that should be
- used to build the components.
-
- Returns:
- BaseModel: The components built based on the config file.
- """
- components = self.component_factory.build_components(
- config_dict=self.config_dict, components_model_type=components_model_type
- )
- return components
-
- def run(self, components: TrainingComponentsInstantiationModel):
- """Entrypoint fo running the training process.
-
- We pass in a TrainingComponentsInstantiationModel,
- which is a pydantic model that contains all the components needed for the training process.
-
- Args:
- components (TrainingComponentsInstantiationModel): The components needed for the training process.
- """
- # save the config file to the checkpointing path
- if components.settings.cuda_env.global_rank == 0:
- experiment_path = components.settings.paths.checkpoint_saving_path / components.settings.experiment_id
- os.makedirs(experiment_path, exist_ok=True)
- shutil.copy(self.config_path, experiment_path / self.config_path.name)
- resolved_config_path = (experiment_path / self.config_path.name).with_suffix(".yaml.resolved")
- with open(resolved_config_path, "w", encoding="utf-8") as f:
- yaml.dump(self.config_dict, f)
-
- evaluation_result_publisher, progress_publisher = self.get_logging_publishers(
- progress_subscriber=components.progress_subscriber,
- results_subscriber=components.evaluation_subscriber,
- global_rank=components.settings.cuda_env.global_rank,
- local_rank=components.settings.cuda_env.local_rank,
- )
-
- # Trainer
- global_num_tokens_per_train_step = (
- components.settings.step_profile.local_train_micro_batch_size
- * components.settings.step_profile.sequence_length
- * components.settings.step_profile.gradient_accumulation_steps
- * components.settings.cuda_env.world_size
- )
- trainer = Trainer(
- global_rank=components.settings.cuda_env.global_rank,
- progress_publisher=progress_publisher,
- num_target_steps=components.settings.training_target.num_target_steps,
- num_target_tokens=components.settings.training_target.num_target_tokens,
- num_seen_train_steps=components.settings.training_progress.num_seen_steps,
- global_num_seen_tokens=components.settings.training_progress.global_num_seen_tokens,
- evaluation_result_publisher=evaluation_result_publisher,
- gradient_acc_steps=components.settings.step_profile.gradient_accumulation_steps,
- gradient_clipper=components.gradient_clipper,
- global_num_tokens_per_train_step=global_num_tokens_per_train_step,
- mfu_calculator=components.mfu_calculator,
- )
-
- # Evaluator
- evaluator = Evaluator(
- progress_publisher=progress_publisher,
- evaluation_result_publisher=evaluation_result_publisher,
- )
-
- # Gym
- gym = Gym(
- trainer=trainer,
- evaluator=evaluator,
- loss_fun=components.loss_fn,
- num_ranks=components.settings.cuda_env.world_size,
- )
- num_params = get_total_number_of_trainable_parameters(components.app_state.model)
- components.evaluation_subscriber.consume_dict({"No. parameters": num_params})
- logging.info(f"Training model with {num_params} parameters.")
-
- print_rank_0(f"Model initialized at {datetime.now()}.")
-
- report = TrainingReportGenerator(
- training_target=components.settings.training_target,
- intervals=components.settings.intervals,
- step_profile=components.settings.step_profile,
- cuda_env=components.settings.cuda_env,
- consistency_enforcement=components.settings.consistency_enforcement,
- train_dataset=components.train_dataset,
- training_progress=components.settings.training_progress,
- ).get_report()
-
- print_rank_0(report)
-
- gym.run(
- train_data_loader=components.train_dataloader,
- evaluation_data_loaders=components.eval_dataloaders,
- checkpoint_saving=components.checkpoint_saving,
- app_state=components.app_state,
- checkpointing_interval_in_steps=components.settings.intervals.checkpointing_interval_in_steps,
- evaluation_interval_in_steps=components.settings.intervals.evaluation_interval_in_steps,
- training_log_interval_in_steps=components.settings.intervals.training_log_interval_in_steps,
- )
-
- def get_logging_publishers(
- self,
- progress_subscriber: MessageSubscriberIF[ProgressUpdate],
- results_subscriber: MessageSubscriberIF[EvaluationResultBatch],
- global_rank: int,
- local_rank: int,
- ) -> tuple[MessagePublisher[EvaluationResultBatch], MessagePublisher[ProgressUpdate]]:
- """Returns the logging publishers for the training.
-
- These publishers are used to pass the evaluation results and the progress updates to the message broker.
- The message broker is then used to pass the messages to the subscribers, such as WandB.
-
- Args:
- progress_subscriber (MessageSubscriberIF[ProgressUpdate]): The progress subscriber
- results_subscriber (MessageSubscriberIF[EvaluationResultBatch]): The results subscriber
- global_rank (int): The global rank of the current process
- local_rank (int): The local rank of the current process on the current node
-
- Returns:
- tuple[MessagePublisher[EvaluationResultBatch], MessagePublisher[ProgressUpdate]]: The evaluation
- result publisher and the progress publisher
- """
- message_broker = MessageBroker()
- progress_publisher = MessagePublisher[ProgressUpdate](
- message_broker=message_broker,
- global_rank=global_rank,
- local_rank=local_rank,
- )
- evaluation_result_publisher = MessagePublisher[EvaluationResultBatch](
- message_broker=message_broker,
- global_rank=global_rank,
- local_rank=local_rank,
- )
+@main.group(name="profile")
+def profile():
+ """
+ Collection of utilities to profile modalities.
+ """
+ pass
- message_broker.add_subscriber(subscription=MessageTypes.EVALUATION_RESULT, subscriber=results_subscriber)
- message_broker.add_subscriber(
- subscription=MessageTypes.BATCH_PROGRESS_UPDATE,
- subscriber=progress_subscriber,
- )
- return evaluation_result_publisher, progress_publisher
+@profile.command(name="train_step")
+@click.option(
+ "--config_file_path",
+ type=click_pathlib.Path(exists=True),
+ required=True,
+ help="Path to the YAML training config file.",
+)
+@click.option(
+ "--experiment_folder_path",
+ type=click_pathlib.Path(file_okay=False),
+ required=True,
+ help="Path to the experiment output directory.",
+)
+@click.option(
+ "--num_warmup_steps",
+ type=int,
+ default=1,
+ show_default=True,
+ help="Number of warmup steps to skip in profiling.",
+)
+@click.option(
+ "--num_measurement_steps",
+ type=int,
+ default=3,
+ show_default=True,
+ help="Number of steps to measure during profiling.",
+)
+def CMD_entry_point_run_train_step_profiler(
+ config_file_path: Path,
+ experiment_folder_path: Path,
+ num_warmup_steps: int,
+ num_measurement_steps: int,
+):
+ """Run train step profiler and write result to JSON if RANK=0."""
+ ModalitiesProfiler.get_train_step_statistics(
+ config_file_path=config_file_path,
+ experiment_folder_path=experiment_folder_path,
+ num_warmup_steps=num_warmup_steps,
+ num_measurement_steps=num_measurement_steps,
+ )
if __name__ == "__main__":
diff --git a/src/modalities/config/config.py b/src/modalities/config/config.py
index 8df8f1daa..fb3cfe896 100644
--- a/src/modalities/config/config.py
+++ b/src/modalities/config/config.py
@@ -315,7 +315,7 @@ class SelectiveLayerACParams(BaseModel):
ac_freq: int
class SelectiveOpACParams(BaseModel):
- pass
+ save_ops_keys: list[str]
sac_variant: SelectiveActivationCheckpointingVariants
layers_fqn: str
diff --git a/src/modalities/config/pydantic_if_types.py b/src/modalities/config/pydantic_if_types.py
index c8dd73f36..ce2f47fdd 100644
--- a/src/modalities/config/pydantic_if_types.py
+++ b/src/modalities/config/pydantic_if_types.py
@@ -25,6 +25,7 @@
from modalities.tokenization.tokenizer_wrapper import TokenizerWrapper
from modalities.training.gradient_clipping.gradient_clipper import GradientClipperIF
from modalities.utils.mfu import MFUCalculatorABC
+from modalities.utils.profilers.batch_generator import DatasetBatchGeneratorIF
class PydanticThirdPartyTypeIF:
@@ -79,3 +80,6 @@ def __get_pydantic_core_schema__(
PydanticDeviceMeshIFType = Annotated[DeviceMesh, PydanticThirdPartyTypeIF(DeviceMesh)]
PydanticAppStateType = Annotated[AppState, PydanticThirdPartyTypeIF(AppState)]
PydanticMFUCalculatorABCType = Annotated[MFUCalculatorABC, PydanticThirdPartyTypeIF(MFUCalculatorABC)]
+PydanticDatasetBatchGeneratorIFType = Annotated[
+ DatasetBatchGeneratorIF, PydanticThirdPartyTypeIF(DatasetBatchGeneratorIF)
+]
diff --git a/src/modalities/main.py b/src/modalities/main.py
new file mode 100644
index 000000000..d995b9168
--- /dev/null
+++ b/src/modalities/main.py
@@ -0,0 +1,214 @@
+import logging
+import os
+import shutil
+from datetime import datetime
+from pathlib import Path
+from typing import Callable, Optional, Type
+
+import yaml
+from pydantic import BaseModel
+
+from modalities.batch import EvaluationResultBatch
+from modalities.config.component_factory import ComponentFactory
+from modalities.config.config import load_app_config_dict
+from modalities.config.instantiation_models import TrainingComponentsInstantiationModel, TrainingReportGenerator
+from modalities.evaluator import Evaluator
+from modalities.gym import Gym
+from modalities.logging_broker.message_broker import MessageBroker
+from modalities.logging_broker.messages import MessageTypes, ProgressUpdate
+from modalities.logging_broker.publisher import MessagePublisher
+from modalities.logging_broker.subscriber import MessageSubscriberIF
+from modalities.registry.components import COMPONENTS
+from modalities.registry.registry import Registry
+from modalities.trainer import Trainer
+from modalities.util import get_synced_experiment_id_of_run, get_total_number_of_trainable_parameters, print_rank_0
+
+
+class Main:
+ """Main class that orchestrates the training process."""
+
+ def __init__(
+ self,
+ config_path: Path,
+ additional_resolver_funs: Optional[dict[str, Callable]] = None,
+ experiment_id: Optional[str] = None,
+ ) -> None:
+ if experiment_id is None:
+ experiment_id = get_synced_experiment_id_of_run(config_path)
+
+ self.config_dict = load_app_config_dict(
+ config_file_path=config_path, experiment_id=experiment_id, additional_resolver_funs=additional_resolver_funs
+ )
+ self.config_path = config_path
+
+ self.registry = Registry(COMPONENTS)
+ self.component_factory = ComponentFactory(registry=self.registry)
+
+ def add_custom_component(
+ self, component_key: str, variant_key: str, custom_component: Type, custom_config: Type
+ ) -> None:
+ """Add a custom component to the registry.
+
+ This method comes in especially handy
+ when Modalities is used as a library and the user wants to add custom components
+ (e.g., custom model or custom loss function) to the registry.
+
+ Args:
+ component_key (str): Key of the component to be added to the registry
+ variant_key (str): Key of the variant to be added to the registry
+ custom_component (Type): The class type of the custom component
+ custom_config (Type): The pydantic config type of the custom component
+ """
+ self.registry.add_entity(
+ component_key=component_key,
+ variant_key=variant_key,
+ component_type=custom_component,
+ component_config_type=custom_config,
+ )
+
+ def build_components(self, components_model_type: Type[BaseModel]) -> BaseModel:
+ """Given a pydantic basemodel, this method builds the components specified in the config file.
+
+ Depending on the use case (e.g., training, inference, etc.), the user can pass different pydantic base models.
+ For instance, for tokenization, the basemodel would only have the tokenization-related components specified.
+
+ Args:
+ components_model_type (Type[BaseModel]): The pydantic basemodel type that should be
+ used to build the components.
+
+ Returns:
+ BaseModel: The components built based on the config file.
+ """
+ components = self.component_factory.build_components(
+ config_dict=self.config_dict, components_model_type=components_model_type
+ )
+ return components
+
+ def run(self, components: TrainingComponentsInstantiationModel):
+ """Entrypoint fo running the training process.
+
+ We pass in a TrainingComponentsInstantiationModel,
+ which is a pydantic model that contains all the components needed for the training process.
+
+ Args:
+ components (TrainingComponentsInstantiationModel): The components needed for the training process.
+ """
+ # save the config file to the checkpointing path
+ if components.settings.cuda_env.global_rank == 0:
+ experiment_path = components.settings.paths.checkpoint_saving_path / components.settings.experiment_id
+ os.makedirs(experiment_path, exist_ok=True)
+ shutil.copy(self.config_path, experiment_path / self.config_path.name)
+ resolved_config_path = (experiment_path / self.config_path.name).with_suffix(".yaml.resolved")
+ with open(resolved_config_path, "w", encoding="utf-8") as f:
+ yaml.dump(self.config_dict, f)
+
+ evaluation_result_publisher, progress_publisher = self.get_logging_publishers(
+ progress_subscriber=components.progress_subscriber,
+ results_subscriber=components.evaluation_subscriber,
+ global_rank=components.settings.cuda_env.global_rank,
+ local_rank=components.settings.cuda_env.local_rank,
+ )
+
+ # Trainer
+ global_num_tokens_per_train_step = (
+ components.settings.step_profile.local_train_micro_batch_size
+ * components.settings.step_profile.sequence_length
+ * components.settings.step_profile.gradient_accumulation_steps
+ * components.settings.cuda_env.world_size
+ )
+ trainer = Trainer(
+ global_rank=components.settings.cuda_env.global_rank,
+ progress_publisher=progress_publisher,
+ num_target_steps=components.settings.training_target.num_target_steps,
+ num_target_tokens=components.settings.training_target.num_target_tokens,
+ num_seen_train_steps=components.settings.training_progress.num_seen_steps,
+ global_num_seen_tokens=components.settings.training_progress.global_num_seen_tokens,
+ evaluation_result_publisher=evaluation_result_publisher,
+ gradient_acc_steps=components.settings.step_profile.gradient_accumulation_steps,
+ gradient_clipper=components.gradient_clipper,
+ global_num_tokens_per_train_step=global_num_tokens_per_train_step,
+ mfu_calculator=components.mfu_calculator,
+ )
+
+ # Evaluator
+ evaluator = Evaluator(
+ progress_publisher=progress_publisher,
+ evaluation_result_publisher=evaluation_result_publisher,
+ )
+
+ # Gym
+ gym = Gym(
+ trainer=trainer,
+ evaluator=evaluator,
+ loss_fun=components.loss_fn,
+ num_ranks=components.settings.cuda_env.world_size,
+ )
+ num_params = get_total_number_of_trainable_parameters(components.app_state.model)
+ components.evaluation_subscriber.consume_dict({"No. parameters": num_params})
+ logging.info(f"Training model with {num_params} parameters.")
+
+ print_rank_0(f"Model initialized at {datetime.now()}.")
+
+ report = TrainingReportGenerator(
+ training_target=components.settings.training_target,
+ intervals=components.settings.intervals,
+ step_profile=components.settings.step_profile,
+ cuda_env=components.settings.cuda_env,
+ consistency_enforcement=components.settings.consistency_enforcement,
+ train_dataset=components.train_dataset,
+ training_progress=components.settings.training_progress,
+ ).get_report()
+
+ print_rank_0(report)
+
+ gym.run(
+ train_data_loader=components.train_dataloader,
+ evaluation_data_loaders=components.eval_dataloaders,
+ checkpoint_saving=components.checkpoint_saving,
+ app_state=components.app_state,
+ checkpointing_interval_in_steps=components.settings.intervals.checkpointing_interval_in_steps,
+ evaluation_interval_in_steps=components.settings.intervals.evaluation_interval_in_steps,
+ training_log_interval_in_steps=components.settings.intervals.training_log_interval_in_steps,
+ )
+
+ def get_logging_publishers(
+ self,
+ progress_subscriber: MessageSubscriberIF[ProgressUpdate],
+ results_subscriber: MessageSubscriberIF[EvaluationResultBatch],
+ global_rank: int,
+ local_rank: int,
+ ) -> tuple[MessagePublisher[EvaluationResultBatch], MessagePublisher[ProgressUpdate]]:
+ """Returns the logging publishers for the training.
+
+ These publishers are used to pass the evaluation results and the progress updates to the message broker.
+ The message broker is then used to pass the messages to the subscribers, such as WandB.
+
+ Args:
+ progress_subscriber (MessageSubscriberIF[ProgressUpdate]): The progress subscriber
+ results_subscriber (MessageSubscriberIF[EvaluationResultBatch]): The results subscriber
+ global_rank (int): The global rank of the current process
+ local_rank (int): The local rank of the current process on the current node
+
+ Returns:
+ tuple[MessagePublisher[EvaluationResultBatch], MessagePublisher[ProgressUpdate]]: The evaluation
+ result publisher and the progress publisher
+ """
+ message_broker = MessageBroker()
+ progress_publisher = MessagePublisher[ProgressUpdate](
+ message_broker=message_broker,
+ global_rank=global_rank,
+ local_rank=local_rank,
+ )
+ evaluation_result_publisher = MessagePublisher[EvaluationResultBatch](
+ message_broker=message_broker,
+ global_rank=global_rank,
+ local_rank=local_rank,
+ )
+
+ message_broker.add_subscriber(subscription=MessageTypes.EVALUATION_RESULT, subscriber=results_subscriber)
+ message_broker.add_subscriber(
+ subscription=MessageTypes.BATCH_PROGRESS_UPDATE,
+ subscriber=progress_subscriber,
+ )
+
+ return evaluation_result_publisher, progress_publisher
diff --git a/src/modalities/models/model_factory.py b/src/modalities/models/model_factory.py
index e48a388a5..99f50e08b 100644
--- a/src/modalities/models/model_factory.py
+++ b/src/modalities/models/model_factory.py
@@ -309,12 +309,22 @@ def get_compiled_model(
"""
def get_parent_module_and_child_name(child_module: nn.Module, model: nn.Module) -> tuple[nn.Module, str]:
+ selected_parent_candidate, selected_child_name = None, None
+ num_candidates = 0
for _, parent_candidate in model.named_modules():
for child_name, child_candidate in parent_candidate.named_children():
if child_candidate is child_module:
- return parent_candidate, child_name
- raise ModelStateError("No valid parent candidate")
+ selected_parent_candidate = parent_candidate
+ selected_child_name = child_name
+ num_candidates += 1
+ if num_candidates == 0:
+ raise ModelStateError("No valid parent candidate")
+ elif num_candidates > 1:
+ raise ModelStateError("Multiple valid parent candidates")
+ else:
+ return selected_parent_candidate, selected_child_name
+ # get all block types that we want to compile individually
block_types = []
for name in block_names:
module_class = get_module_class_from_name(model, name)
diff --git a/src/modalities/registry/components.py b/src/modalities/registry/components.py
index 916dc8cb3..f3e54e5fb 100644
--- a/src/modalities/registry/components.py
+++ b/src/modalities/registry/components.py
@@ -111,6 +111,7 @@
NumTokensFromNumStepsConfig,
NumTokensFromPackedMemMapDatasetContinuousConfig,
)
+from modalities.utils.profilers.batch_generator import RandomDatasetBatchGenerator, RandomDatasetBatchGeneratorConfig
@dataclass
@@ -226,6 +227,10 @@ class ComponentEntity:
ComponentEntity("collate_fn", "coca_collator", CoCaCollatorFn, CoCaCollateFnConfig),
# data loaders
ComponentEntity("data_loader", "default", DataloaderFactory.get_dataloader, LLMDataLoaderConfig),
+ # dataset batch generator
+ ComponentEntity(
+ "dataset_batch_generator", "random", RandomDatasetBatchGenerator, RandomDatasetBatchGeneratorConfig
+ ),
# checkpointing
ComponentEntity("checkpoint_saving", "default", CheckpointSaving, CheckpointSavingConfig),
# checkpointing strategies
diff --git a/src/modalities/running_env/cuda_env.py b/src/modalities/running_env/cuda_env.py
index 8d2a17d5c..6559f6975 100644
--- a/src/modalities/running_env/cuda_env.py
+++ b/src/modalities/running_env/cuda_env.py
@@ -1,4 +1,5 @@
import os
+from datetime import timedelta
from typing import Any
import torch
@@ -27,14 +28,14 @@ def __enter__(self) -> "CudaEnv":
Returns:
CudaEnv: Instance of the CudaEnv context manager.
"""
- dist.init_process_group(self.process_group_backend.value)
+ dist.init_process_group(self.process_group_backend.value, timeout=timedelta(seconds=10))
local_rank = int(os.getenv("LOCAL_RANK", "-1"))
if local_rank == -1:
raise ValueError("LOCAL_RANK environment variable is not set. Please set it before using CudaEnv.")
torch.cuda.set_device(local_rank)
return self
- def __exit__(self, type: Any, value: Any, traceback: Any):
+ def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
"""Exits the CUDA environment for distributed training by destroying the process group.
Args:
@@ -42,8 +43,13 @@ def __exit__(self, type: Any, value: Any, traceback: Any):
value (Any):
traceback (Any):
"""
- # TODO and NOTE:
- # when we call barrier here and one of the ranks fails, we get stuck here.
- # In the future, we should probably add a timeout here and handle the case when one of the ranks fails.
- # dist.barrier()
- dist.destroy_process_group()
+ local_rank = int(os.getenv("LOCAL_RANK", "-1"))
+ if exc_type is torch.cuda.OutOfMemoryError:
+ print(f"[Rank {local_rank}] CUDA OOM during block, emptying cache.")
+ torch.cuda.empty_cache()
+
+ try:
+ if dist.is_initialized():
+ dist.destroy_process_group()
+ except Exception as e:
+ print(f"[Rank {local_rank}] Error during process group cleanup: {e}")
diff --git a/src/modalities/training/activation_checkpointing/activation_checkpointing.py b/src/modalities/training/activation_checkpointing/activation_checkpointing.py
index c71900cd4..77ad87dc8 100644
--- a/src/modalities/training/activation_checkpointing/activation_checkpointing.py
+++ b/src/modalities/training/activation_checkpointing/activation_checkpointing.py
@@ -1,8 +1,10 @@
from collections import defaultdict
from functools import partial
+from typing import Set
import torch
import torch.nn as nn
+import torch.ops as ops
from torch.distributed.algorithms._checkpoint.checkpoint_wrapper import CheckpointImpl, apply_activation_checkpointing
from torch.distributed.algorithms._checkpoint.checkpoint_wrapper import checkpoint_wrapper as ptd_checkpoint_wrapper
from torch.distributed.fsdp.fully_sharded_data_parallel import FullyShardedDataParallel as FSDP1
@@ -59,6 +61,24 @@ class SelectiveActivationCheckpointing:
"""
+ SAVE_DICT = {
+ # as prposed by torch titan
+ # https://github.com/pytorch/torchtitan/blob/30b9ea0b1ad893379d2ff3b12dbf18600730c249/torchtitan/models/llama3/parallelize_llama.py#L218
+ # This is the list of ops that are saved by default in torch titan.
+ # These operations are typically compute intensive and their activations are
+ # therefore saved and not recomputed in the backward pass.
+ # This list differs from the compute intensive ops list in the
+ # pytorch AC tutorial: https://pytorch.org/blog/activation-checkpointing-techniques/
+ "ops.aten.mm.default": ops.aten.mm.default,
+ "ops.aten._scaled_dot_product_efficient_attention.default": ops.aten._scaled_dot_product_efficient_attention.default, # noqa
+ "ops.aten._scaled_dot_product_flash_attention.default": ops.aten._scaled_dot_product_flash_attention.default,
+ "ops._c10d_functional.reduce_scatter_tensor.default": ops._c10d_functional.reduce_scatter_tensor.default,
+ # for low precision training, it's useful to always save
+ # the result of max, since the absolute maximum is
+ # used to compute the scaling factor for quantization.
+ "torch.ops.aten.max.default": ops.aten.max.default,
+ }
+
@staticmethod
def apply_selective_activation_checkpointing_(
sac_variant: SelectiveActivationCheckpointingVariants,
@@ -101,7 +121,15 @@ def apply_selective_activation_checkpointing_(
ac_freq=sac_fun_params.ac_freq,
)
elif sac_variant == SelectiveActivationCheckpointingVariants.SELECTIVE_OP_ACTIVATION_CHECKPOINTING:
- apply_ac_fun = SelectiveActivationCheckpointing._apply_selective_op_ac
+ if len(sac_fun_params.save_ops_keys) > 0:
+ apply_ac_fun = partial(
+ SelectiveActivationCheckpointing._apply_selective_op_ac, save_ops_keys=sac_fun_params.save_ops_keys
+ )
+ else:
+
+ def apply_ac_fun(model):
+ return model
+
else:
raise ValueError(f"Unknown activation checkpointing variant: {sac_variant}")
@@ -125,55 +153,27 @@ def _apply_full_ac(module: nn.Module) -> nn.Module:
return module_saced
@staticmethod
- def _apply_selective_op_ac(module: nn.Module) -> nn.Module:
- def _get_custom_policy(meta, save_list): # closure to capture meta
+ def _apply_selective_op_ac(module: nn.Module, save_ops_keys: list[str]) -> nn.Module:
+ def _get_custom_policy(meta, save_ops_set: Set): # closure to capture meta
def _custom_policy(ctx, func, *args, **kwargs):
mode = "recompute" if ctx.is_recompute else "forward"
mm_count_key = f"{mode}_mm_count"
if func == torch.ops.aten.mm.default:
meta[mm_count_key] += 1
# Saves output of all compute ops, except every second mm
- to_save = func in save_list and not (func == torch.ops.aten.mm.default and meta[mm_count_key] % 2 == 0)
+ # NOTE: we should make this configurable and not hide it in the code
+ to_save = func in save_ops_set and not (
+ func == torch.ops.aten.mm.default and meta[mm_count_key] % 2 == 0
+ )
return CheckpointPolicy.MUST_SAVE if to_save else CheckpointPolicy.PREFER_RECOMPUTE
return _custom_policy
def _selective_checkpointing_context_fn():
meta = defaultdict(int)
- # This is the list of ops that are saved by default in torch titan.
- # These operations are typically compute intensive and their activations are
- # therefore saved and not recomputed in the backward pass.
- # This list differs from the compute intensive ops list in the
- # pytorch AC tutorial: https://pytorch.org/blog/activation-checkpointing-techniques/
- # TODO: Optimize this list for our GP2 implementation!
- save_list = { # default save list from torch titan
- torch.ops.aten.mm.default,
- torch.ops.aten._scaled_dot_product_efficient_attention.default,
- torch.ops.aten._scaled_dot_product_flash_attention.default,
- torch.ops._c10d_functional.reduce_scatter_tensor.default,
- # for low precision training, it's useful to always save
- # the result of max, since the absolute maximum is
- # used to compute the scaling factor for quantization.
- torch.ops.aten.max.default,
- # # pytorch tutorial ATen ops
- # torch.ops.aten.mm,
- # torch.ops.aten.convolution,
- # torch.ops.aten.convolution_backward,
- # torch.ops.aten.bmm,
- # torch.ops.aten.addmm,
- # torch.ops.aten._scaled_dot_product_flash_attention,
- # torch.ops.aten._scaled_dot_product_efficient_attention,
- # torch.ops.aten._flash_attention_forward,
- # torch.ops.aten._efficient_attention_forward,
- # torch.ops.aten.upsample_bilinear2d,
- # torch.ops.aten._scaled_mm,
- # # mine
- # torch.ops.aten.add.Tensor,
- # #torch.ops.aten.mul.Tensor
- }
- # For now, we only allow for a single AC policy
- # (i.e., the torch titan LLama 3 one) to be used
- policy = _get_custom_policy(meta, save_list)
+ save_ops_set = {SelectiveActivationCheckpointing.SAVE_DICT[key] for key in save_ops_keys}
+
+ policy = _get_custom_policy(meta=meta, save_ops_set=save_ops_set)
return create_selective_checkpoint_contexts(policy_fn_or_list=policy)
module_saced = ptd_checkpoint_wrapper(
diff --git a/src/modalities/util.py b/src/modalities/util.py
index a970137ea..003586683 100644
--- a/src/modalities/util.py
+++ b/src/modalities/util.py
@@ -1,4 +1,5 @@
import hashlib
+import os
import time
import warnings
from datetime import datetime
@@ -47,15 +48,59 @@ def parse_enum_by_name(name: str, enum_type: Type[Enum]) -> Enum:
raise ValidationError(f"Invalid {enum_type} member name: {name}")
-def get_experiment_id_of_run(
- config_file_path: Path, hash_length: Optional[int] = 8, max_experiment_id_byte_length: Optional[int] = 1024
+def get_experiment_id_from_config(config_file_path: Optional[Path], hash_length: Optional[int] = 8) -> str:
+ """Create experiment ID including the date and time for file save uniqueness
+ example: 2022-05-07__14-31-22_fdh1xaj2'
+ """
+ date_of_run = datetime.now().strftime("%Y-%m-%d__%H-%M-%S")
+
+ if config_file_path is None:
+ experiment_id = f"{date_of_run}"
+ else:
+ hash = hashlib.sha256(str(config_file_path).encode()).hexdigest()[:hash_length]
+ experiment_id = f"{date_of_run}_{hash}"
+
+ return experiment_id
+
+
+def get_synced_string(
+ string_to_be_synced: str, from_rank: int = 0, max_string_byte_length: Optional[int] = 1024
+) -> str:
+ rank = dist.get_rank()
+ if rank == from_rank:
+ # Generate a unique folder name
+ string_to_be_synced_bytes = string_to_be_synced.encode("utf-8")
+ if len(string_to_be_synced_bytes) > max_string_byte_length:
+ raise ValueError(
+ f"Experiment ID is too long: {len(string_to_be_synced_bytes)} bytes, "
+ f"max length is {max_string_byte_length} bytes"
+ )
+ else:
+ string_to_be_synced_bytes = bytearray(max_string_byte_length) # Preallocate buffer for receiving
+
+ # Ensure all ranks have the same folder name
+ string_to_be_synced_tensor = torch.tensor(
+ list(string_to_be_synced_bytes) + [0] * (max_string_byte_length - len(string_to_be_synced_bytes)),
+ dtype=torch.uint8,
+ ).cuda()
+ dist.broadcast(string_to_be_synced_tensor, src=from_rank)
+
+ # Decode on all ranks
+ synced_string = string_to_be_synced_tensor.cpu().numpy().tobytes().decode("utf-8").rstrip("\x00")
+ return synced_string
+
+
+def get_synced_experiment_id_of_run(
+ config_file_path: Optional[Path] = None,
+ hash_length: Optional[int] = 8,
+ max_experiment_id_byte_length: Optional[int] = 1024,
) -> str:
"""Create a unique experiment ID for the current run on rank 0 and broadcast it to all ranks.
Internally, the experiment ID is generated by hashing the configuration file path and appending
the current date and time.
The experiment ID is then converted to a byte array (with maximum length of max_experiment_id_byte_length) and
broadcasted to all ranks. In the unlikely case of the experiment ID being too long, a ValueError is raised
- and max_experment_id_byte_length must be increased. Each rank then decodes the byte array to the original
+ and max_experiment_id_byte_length must be increased. Each rank then decodes the byte array to the original
string representation and returns it. Having a globally synced experiment ID is mandatory for
saving files / checkpionts in a distributed training setup.
@@ -68,40 +113,16 @@ def get_experiment_id_of_run(
Returns:
str: The experiment ID.
"""
-
- def get_experiment_id_from_config(config_file_path: Path, hash_length: Optional[int] = 8) -> str:
- """Create experiment ID including the date and time for file save uniqueness
- example: 2022-05-07__14-31-22_fdh1xaj2'
- """
- hash = hashlib.sha256(str(config_file_path).encode()).hexdigest()[:hash_length]
- date_of_run = datetime.now().strftime("%Y-%m-%d__%H-%M-%S")
- experiment_id = f"{date_of_run}_{hash}"
- return experiment_id
-
rank = dist.get_rank()
- if rank == 0:
- # Generate a unique folder name
- experimenet_id = get_experiment_id_from_config(config_file_path, hash_length)
- experiment_id_bytes = experimenet_id.encode("utf-8")
- if len(experiment_id_bytes) > max_experiment_id_byte_length:
- raise ValueError(
- f"Experiment ID is too long: {len(experiment_id_bytes)} bytes, "
- f"max length is {max_experiment_id_byte_length} bytes"
- )
- print(f"Rank 0 generated experiment_id: {experimenet_id}")
- else:
- experiment_id_bytes = bytearray(max_experiment_id_byte_length) # Preallocate buffer for receiving
-
- # Ensure all ranks have the same folder name
- experiment_id_tensor = torch.tensor(
- list(experiment_id_bytes) + [0] * (max_experiment_id_byte_length - len(experiment_id_bytes)), dtype=torch.uint8
- ).cuda()
- dist.broadcast(experiment_id_tensor, src=0)
-
+ experimenet_id = get_experiment_id_from_config(config_file_path, hash_length)
+ experiment_id_synced = get_synced_string(
+ string_to_be_synced=experimenet_id,
+ from_rank=0,
+ max_string_byte_length=max_experiment_id_byte_length,
+ )
# Decode on all ranks
- experiment_id = experiment_id_tensor.cpu().numpy().tobytes().decode("utf-8").rstrip("\x00")
- print(f"Rank {rank} received experiment_id: {experiment_id}")
- return experiment_id
+ print(f"Rank {rank} received experiment_id: {experiment_id_synced}")
+ return experiment_id_synced
def format_metrics_to_gb(item):
@@ -293,3 +314,7 @@ def get_module_class_from_name(module: torch.nn.Module, name: str) -> Type[torch
module_class = get_module_class_from_name(child_module, name)
if module_class is not None:
return module_class
+
+
+def is_launched_via_torchrun() -> bool:
+ return all(env_var in os.environ for env_var in ["RANK", "LOCAL_RANK", "WORLD_SIZE", "MASTER_ADDR", "MASTER_PORT"])
diff --git a/src/modalities/utils/profilers/README.md b/src/modalities/utils/profilers/README.md
new file mode 100644
index 000000000..b29ab6da9
--- /dev/null
+++ b/src/modalities/utils/profilers/README.md
@@ -0,0 +1,20 @@
+# Modalities Profiling
+
+## Activation Checkpointing
+
+### Selective Activation Checkpointing
+
+With **selective activation checkpointing (SAC)**, we reduce the memory footprint at the expense of increased compute by saving **only the activations of selected ATen ops**.
+To make SAC effective, we focus on ATen ops that are **memory-intensive yet fast to recompute**.
+
+In Modalities, we follow an iterative process to determine which ops to save:
+
+1. **Establish a baseline**
+ Run a training step with the maximum batch size that fits in memory *without* any activation checkpointing. Record the total memory footprint and runtime.
+
+2. **Profile the forward pass**
+ Use the PyTorch profiler to identify compute-heavy ops. These are typically associated with attention (e.g., flash attention, matmuls, etc.).
+
+3. **Estimate op memory cost indirectly**
+ Because PyTorch's profiler doesn't always attribute memory allocations to the corresponding ATen ops, we rely on **step-level peak memory tracking** (`torch.cuda.max_memory_allocated`) instead.
+ We **experiment with different save lists in isolation**, and compare the resulting memory footprint and runtime against the baseline from step 1.
diff --git a/src/modalities/utils/profilers/__init__.py b/src/modalities/utils/profilers/__init__.py
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/src/modalities/utils/profilers/__init__.py
@@ -0,0 +1 @@
+
diff --git a/src/modalities/utils/profilers/batch_generator.py b/src/modalities/utils/profilers/batch_generator.py
new file mode 100644
index 000000000..ba6d19016
--- /dev/null
+++ b/src/modalities/utils/profilers/batch_generator.py
@@ -0,0 +1,31 @@
+from abc import ABC
+
+import torch
+from pydantic import BaseModel
+
+from modalities.batch import DatasetBatch
+
+
+class RandomDatasetBatchGeneratorConfig(BaseModel):
+ vocab_size: int
+ sequence_length: int
+ batch_size: int
+
+
+class DatasetBatchGeneratorIF(ABC):
+ def get_dataset_batch(self) -> DatasetBatch:
+ raise NotImplementedError
+
+
+class RandomDatasetBatchGenerator(DatasetBatchGeneratorIF):
+ def __init__(self, vocab_size: int, sequence_length: int, batch_size: int):
+ self._vocab_size = vocab_size
+ self._sequence_length = sequence_length
+ self._batch_size = batch_size
+
+ def get_dataset_batch(self) -> DatasetBatch:
+ batch = DatasetBatch(
+ samples={"input_ids": torch.randint(0, self._vocab_size, (self._batch_size, self._sequence_length))},
+ targets={"target_ids": torch.randint(0, self._vocab_size, (self._batch_size, self._sequence_length))},
+ )
+ return batch
diff --git a/src/modalities/utils/profilers/grid_search_utils.py b/src/modalities/utils/profilers/grid_search_utils.py
new file mode 100644
index 000000000..d60b2d2a5
--- /dev/null
+++ b/src/modalities/utils/profilers/grid_search_utils.py
@@ -0,0 +1,54 @@
+import copy
+from dataclasses import dataclass
+from itertools import product
+from typing import Any
+
+
+@dataclass
+class GridSearchItem:
+ name: str
+ values: list[Any]
+
+
+@dataclass
+class ConfigValue:
+ name: str
+ value: Any
+
+
+class GridSearchUtils:
+ @staticmethod
+ def get_configs_from_grid_search(
+ config_dict: dict[str, Any], grid_search: list[GridSearchItem]
+ ) -> list[dict[str, ConfigValue]]:
+ def _get_cartesian_product(grid_search: list[GridSearchItem]) -> list[dict[str, ConfigValue]]:
+ # Extract all names, values, and config_path flags
+ names = [item.name for item in grid_search]
+ value_lists = [item.values for item in grid_search]
+
+ result = []
+ for combination in product(*value_lists):
+ config = {name: ConfigValue(name=name, value=value) for name, value in zip(names, combination)}
+ result.append(config)
+ return result
+
+ def _add_config_updates(
+ config_dict: dict[str, Any], grid_search_config: dict[str, ConfigValue]
+ ) -> dict[str, Any]:
+ config_dict_copy = copy.deepcopy(config_dict)
+ # for each update
+ for path_string, config_value in grid_search_config.items():
+ path_list = config_value.name.split(".")
+ current_config_dict = config_dict_copy
+ # traverse to the object to update
+ for key in path_list[:-1]:
+ current_config_dict = current_config_dict[key]
+ # update the object
+ current_config_dict[path_list[-1]] = config_value.value
+ # return adapted config
+ return config_dict_copy
+
+ grid_search_configs: list[dict[str, ConfigValue]] = _get_cartesian_product(grid_search=grid_search)
+
+ grid_search_configs_updated = [_add_config_updates(config_dict, gs_config) for gs_config in grid_search_configs]
+ return grid_search_configs_updated
diff --git a/src/modalities/utils/profilers/modalities_profiler.py b/src/modalities/utils/profilers/modalities_profiler.py
new file mode 100644
index 000000000..00ed9ae07
--- /dev/null
+++ b/src/modalities/utils/profilers/modalities_profiler.py
@@ -0,0 +1,292 @@
+import hashlib
+import json
+import os
+import socket
+import time
+from collections import defaultdict
+from dataclasses import asdict, dataclass
+from enum import Enum
+from pathlib import Path
+from typing import Callable, Optional
+
+import numpy as np
+import torch
+import yaml
+from pydantic import BaseModel
+
+from modalities.batch import DatasetBatch, InferenceResultBatch
+from modalities.config.config import ProcessGroupBackendType
+from modalities.config.pydantic_if_types import (
+ PydanticDatasetBatchGeneratorIFType,
+ PydanticFSDP2ModuleType,
+ PydanticLossIFType,
+ PydanticOptimizerIFType,
+)
+from modalities.loss_functions import Loss
+from modalities.main import Main
+from modalities.running_env.cuda_env import CudaEnv
+from modalities.util import get_synced_string
+from modalities.utils.profilers.batch_generator import DatasetBatchGeneratorIF
+from modalities.utils.profilers.grid_search_utils import ConfigValue
+from modalities.utils.typing_utils import FSDPX
+
+
+class InstantiationModel(BaseModel):
+ initialized_model: PydanticFSDP2ModuleType
+ loss_fn: PydanticLossIFType
+ optimizer: Optional[PydanticOptimizerIFType] = None
+ dataset_batch_generator: PydanticDatasetBatchGeneratorIFType
+
+
+class TrainStepMetrics(Enum):
+ FORWARD_PASS_TIME_s = "forward_pass_time_s"
+ BACKWARD_PASS_TIME_s = "backward_pass_time_s"
+ OPTIMIZER_STEP_TIME_s = "optimizer_step_time_s"
+ PEAK_MEMORY_MB = "peak_memory_MB"
+
+
+class TrainStepStatistics:
+ def __init__(self, global_rank: int, local_rank: int, num_ranks: int):
+ self._global_rank: int = global_rank
+ self._local_rank: int = local_rank
+ self._num_ranks: int = num_ranks
+ self._measurements_dict: dict[TrainStepMetrics, float] = defaultdict(list)
+
+ @property
+ def num_ranks(self) -> int:
+ return self._num_ranks
+
+ def add_measurement(self, step: TrainStepMetrics, time: float):
+ self._measurements_dict[step].append(time)
+
+ def add_measurements(self, measurements: dict[TrainStepMetrics, float]):
+ for key, value in measurements.items():
+ self._measurements_dict[key].append(value)
+
+ def get_mean_measurements_dict(
+ self,
+ ) -> dict[TrainStepMetrics, float]:
+ return {key: np.mean(values) for key, values in self._measurements_dict.items()}
+
+ def __repr__(self):
+ mean_measurements = self.get_mean_measurements_dict()
+ mean_measurements["TOTAL_STEP_TIME_s"] = (
+ mean_measurements[TrainStepMetrics.FORWARD_PASS_TIME_s]
+ + mean_measurements[TrainStepMetrics.BACKWARD_PASS_TIME_s]
+ + mean_measurements[TrainStepMetrics.OPTIMIZER_STEP_TIME_s]
+ )
+ lines = ["\nStep statistics global rank {} (local rank: {}):".format(self._global_rank, self._local_rank)]
+ lines.append(f"{'Measurement':<30} {'Value':>10}")
+ lines.extend([f"{k.name:<30} {v:>10.3f}" for k, v in mean_measurements.items()])
+ return "\n".join(lines)
+
+
+@dataclass
+class Result:
+ @dataclass
+ class Measurement:
+ peak_memory: float
+ forward_time: float
+ backward_time: float
+ step_time: float
+
+ @dataclass
+ class EnvInfo:
+ local_rank: int
+ global_rank: int
+ num_ranks: int
+ hostname: str
+
+ @staticmethod
+ def from_env() -> "Result.EnvInfo":
+ local_rank = int(os.environ.get("LOCAL_RANK", 0))
+ global_rank = int(os.environ.get("RANK", 0)) # torchrun uses RANK for global rank
+ num_ranks = int(os.environ.get("WORLD_SIZE", 0))
+ hostname = socket.gethostname()
+ return Result.EnvInfo(
+ local_rank=local_rank, global_rank=global_rank, num_ranks=num_ranks, hostname=hostname
+ )
+
+ grid_search_config: dict[str, ConfigValue]
+ env_info: EnvInfo
+ measurement: Measurement
+ error: str = ""
+
+
+class ModalitiesProfiler:
+ @staticmethod
+ def get_train_step_statistics(
+ config_file_path: Path,
+ experiment_folder_path: Path,
+ num_warmup_steps: int,
+ num_measurement_steps: int,
+ ) -> Result:
+ """Profiles the training step of a model using the given config file and experiment folder path
+ w.r.t. peak memory, as well as, forward, backward and step time.
+
+ Args:
+ config_file_path (Path): Path to the config file.
+ experiment_folder_path (Path): Path to the experiment folder.
+ num_warmup_steps (int): Number of warmup steps to be used for the profiler.
+ No measurements are taken during the warmup steps.
+ num_measurement_steps (int): Number of measurement steps to be used for the profiler.
+
+ Returns:
+ Result: A dataclass containing the profiling results, including peak memory, forward time,
+ backward time, step time, and any error messages.
+ """
+ error = ""
+ try:
+ with CudaEnv(process_group_backend=ProcessGroupBackendType.nccl):
+ experiment_folder_path = Path(
+ get_synced_string(string_to_be_synced=str(experiment_folder_path), from_rank=0)
+ )
+
+ step_statistics = ModalitiesProfiler._get_train_step_statistics_impl(
+ config_file_path=config_file_path,
+ num_warmup_steps=num_warmup_steps,
+ num_measurement_steps=num_measurement_steps,
+ )
+ mean_statistics = step_statistics.get_mean_measurements_dict()
+ except Exception as e:
+ error = str(e)
+ mean_statistics = defaultdict(lambda: -1)
+
+ with open(config_file_path, "r") as f:
+ config_dict = yaml.safe_load(f)
+
+ result = Result(
+ grid_search_config=config_dict["settings"]["benchmark"],
+ measurement=Result.Measurement(
+ peak_memory=mean_statistics[TrainStepMetrics.PEAK_MEMORY_MB],
+ forward_time=mean_statistics[TrainStepMetrics.FORWARD_PASS_TIME_s],
+ backward_time=mean_statistics[TrainStepMetrics.BACKWARD_PASS_TIME_s],
+ step_time=mean_statistics[TrainStepMetrics.OPTIMIZER_STEP_TIME_s],
+ ),
+ env_info=Result.EnvInfo.from_env(),
+ error=error,
+ )
+ # write results to json on all ranks
+ current_rank = int(os.environ["RANK"])
+ hash = hashlib.sha256(str(config_dict).encode()).hexdigest()[:8]
+
+ result_file_path = experiment_folder_path / f"{hash}_{current_rank}.json"
+ # create folder if not exists
+ result_file_path.parent.mkdir(parents=True, exist_ok=True)
+ with open(result_file_path, "w") as f:
+ json.dump(asdict(result), f, indent=4)
+ return result
+
+ @staticmethod
+ def _get_train_step_statistics_impl(
+ config_file_path: Path,
+ num_warmup_steps: int,
+ num_measurement_steps: int,
+ ) -> TrainStepStatistics:
+ torch.distributed.barrier()
+ torch.cuda.empty_cache()
+ torch.distributed.barrier()
+
+ main_obj = Main(config_file_path)
+ components = main_obj.build_components(components_model_type=InstantiationModel)
+ model = components.initialized_model
+ loss_fun: Loss = components.loss_fn
+ optimizer: Optional[torch.optim.Optimizer] = components.optimizer
+ batch_generator: DatasetBatchGeneratorIF = components.dataset_batch_generator
+ statistics = TrainStepStatistics(
+ global_rank=int(os.environ["RANK"]),
+ local_rank=int(os.environ["LOCAL_RANK"]),
+ num_ranks=torch.distributed.get_world_size(),
+ )
+ for _ in range(num_warmup_steps):
+ ModalitiesProfiler._run_train_step(
+ model=model,
+ batch_generator=batch_generator,
+ loss_fun=loss_fun,
+ optimizer=optimizer,
+ )
+ for _ in range(num_measurement_steps):
+ measurements_dict = ModalitiesProfiler._run_train_step(
+ model=model,
+ batch_generator=batch_generator,
+ loss_fun=loss_fun,
+ optimizer=optimizer,
+ )
+ statistics.add_measurements(measurements=measurements_dict)
+
+ return statistics
+
+ @staticmethod
+ def get_forward_pass_profiling(
+ config_file_path: Path,
+ num_measurement_steps: int,
+ profile_context_manager: torch.profiler.profile,
+ ) -> TrainStepStatistics:
+ with CudaEnv(process_group_backend=ProcessGroupBackendType.nccl):
+ main_obj = Main(config_file_path)
+ components = main_obj.build_components(components_model_type=InstantiationModel)
+ model = components.initialized_model
+ loss_fun: Loss = components.loss_fn
+ dataset_batch_generator: DatasetBatchGeneratorIF = components.dataset_batch_generator
+ device = torch.device(f"cuda:{int(os.environ['LOCAL_RANK'])}")
+ with profile_context_manager as profiler:
+ for _ in range(num_measurement_steps):
+ batch = dataset_batch_generator.get_dataset_batch()
+ batch.to(device=device)
+ torch.distributed.barrier()
+ ModalitiesProfiler._run_forward_pass(
+ model=model,
+ batch=batch,
+ loss_fun=loss_fun,
+ )
+ profiler.step()
+
+ @staticmethod
+ def _run_train_step(
+ model: FSDPX,
+ batch_generator: DatasetBatchGeneratorIF,
+ loss_fun: Callable,
+ optimizer: Optional[torch.optim.Optimizer] = None,
+ ) -> dict[TrainStepMetrics, float]:
+ device = torch.device(f"cuda:{int(os.environ['RANK'])}")
+ # generate batch
+ batch = batch_generator.get_dataset_batch()
+ batch.to(device=device)
+
+ # forward pass
+ torch.cuda.reset_peak_memory_stats(device)
+ start_forward = time.time()
+ predictions = model(batch.samples)
+ forward_time = time.time() - start_forward
+
+ result_batch = InferenceResultBatch(targets=batch.targets, predictions=predictions)
+ loss = loss_fun(result_batch)
+
+ # backward pass
+ start_backward = time.time()
+ loss.backward()
+ backward_time = time.time() - start_backward
+
+ # optimizer step
+ if optimizer is not None:
+ start_step = time.time()
+ optimizer.step()
+ optimizer.zero_grad()
+ step_time = time.time() - start_step
+
+ # calculate the peak memory
+ peak_memory = torch.cuda.max_memory_allocated(device) / 1024**2 # in MB
+ batch_size = batch.samples["input_ids"].shape[0]
+ return {
+ TrainStepMetrics.FORWARD_PASS_TIME_s: forward_time / batch_size, # per sample
+ TrainStepMetrics.BACKWARD_PASS_TIME_s: backward_time / batch_size,
+ TrainStepMetrics.OPTIMIZER_STEP_TIME_s: step_time / batch_size,
+ TrainStepMetrics.PEAK_MEMORY_MB: peak_memory,
+ }
+
+ @staticmethod
+ def _run_forward_pass(model: FSDPX, batch: DatasetBatch, loss_fun: Optional[Callable] = None) -> None:
+ predictions = model(batch.samples)
+ result_batch = InferenceResultBatch(targets=batch.targets, predictions=predictions)
+ if loss_fun is not None:
+ loss_fun(result_batch)
diff --git a/src/modalities/utils/profilers/profile_logs_analyzers.py b/src/modalities/utils/profilers/profile_logs_analyzers.py
new file mode 100644
index 000000000..f47c7bdd6
--- /dev/null
+++ b/src/modalities/utils/profilers/profile_logs_analyzers.py
@@ -0,0 +1,73 @@
+import json
+from dataclasses import asdict
+from pathlib import Path
+
+import pandas as pd
+
+from modalities.utils.profilers.modalities_profiler import Result
+
+
+class ProfileLogsAnalyzer:
+ @staticmethod
+ def load_profiling_logs(log_dir_path: Path) -> list[Result]:
+ """
+ Loads the profiling logs from the specified directory.
+
+ Args:
+ log_dir_path (Path): The path to the directory containing the profiling logs.
+
+ Returns:
+ list[Result]: A list of profiling results.
+ """
+ results = []
+ for file in log_dir_path.glob("*.json"):
+ with open(file, "r") as f:
+ data = json.load(f)
+ result = Result(
+ grid_search_config=data["grid_search_config"],
+ env_info=data["env_info"],
+ measurement=Result.Measurement(**data["measurement"]),
+ error=data.get("error", ""),
+ )
+ results.append(result)
+ return results
+
+ @staticmethod
+ def to_pandas_df(results: list[Result]) -> pd.DataFrame:
+ """
+ Converts the profiling results to a pandas DataFrame.
+
+ Args:
+ results (list[Result]): The list of profiling results.
+
+ Returns:
+ pd.DataFrame: A DataFrame containing the profiling results.
+ """
+ data = []
+ for result in results:
+ result_dict = asdict(result)
+ # Flatten the 'measurement' dict into the top-level dict
+ measurement = result_dict.pop("measurement", {})
+ # Flatten the 'grid_search_config' dict into the top-level dict
+ grid_search_config = result_dict.pop("grid_search_config", {})
+ # Flatten the 'env_info' dict into the top-level dict
+ env_info = result_dict.pop("env_info", {})
+ flat_result = {**grid_search_config, **env_info, **measurement, **result_dict}
+ data.append(flat_result)
+ return pd.DataFrame(data)
+
+
+if __name__ == "__main__":
+ # Example usage
+ log_dir = Path(
+ "/raid/s3/opengptx/max_lue/repositories/modalities/tests/training/benchmark/2025-04-24__18-18-58_ed5e5044"
+ )
+ results = ProfileLogsAnalyzer.load_profiling_logs(log_dir)
+ df = ProfileLogsAnalyzer.to_pandas_df(results)
+ df["total_step_time"] = df["forward_time"] + df["backward_time"] + df["step_time"]
+ df.sort_values(by=["total_step_time"], inplace=True, ascending=True)
+ df["error"] = df["error"].apply(lambda x: x[:20])
+ with pd.option_context(
+ "display.max_rows", None, "display.max_columns", None, "display.width", None, "display.max_colwidth", None
+ ):
+ print(df)
diff --git a/src/modalities/utils/profilers/profiler_starters.py b/src/modalities/utils/profilers/profiler_starters.py
new file mode 100644
index 000000000..5d1afd1b1
--- /dev/null
+++ b/src/modalities/utils/profilers/profiler_starters.py
@@ -0,0 +1,145 @@
+import tempfile
+from pathlib import Path
+
+import tqdm
+import yaml
+from torch.profiler import ProfilerActivity, profile, schedule
+
+from modalities import __main__
+from modalities.util import is_launched_via_torchrun
+from modalities.utils.profilers.grid_search_utils import GridSearchItem, GridSearchUtils
+from modalities.utils.profilers.modalities_profiler import ModalitiesProfiler
+from modalities.utils.run_torchrun_script import run_torchrun_with_cleanup
+
+
+class ModalitiesProfilerStarter:
+ @staticmethod
+ def run_train_step_profiler(
+ config_file_path: Path,
+ experiment_folder_path: Path,
+ grid_search: list[GridSearchItem],
+ num_warmup_steps: int,
+ num_measurement_steps: int,
+ nproc_per_node: int = 1,
+ num_nodes: int = 1,
+ node_rank: int = 0,
+ rdzv_endpoint: str = "localhost:0",
+ ):
+ """Applies memory and runtime profiling to the training step of a model training.
+ By specifying a grid search, the profiler can be run for multiple configurations.
+ Internally, the grid search (i.e., the cartesian product of all settings) is applied
+ to the config file and a new temporary config file is created for each grid search item.
+ The profiler is then run sequentially for each config file.
+
+ This function can be run in two ways:
+ 1) Can be called directly from the command line. In this case, the profiler runs a
+ torchrun environment internally that gets destroyed after running each config.
+ This makes sure that the profiler is run in a clean environment and that the
+ processes are not within an undefined state after OOM errors.
+ 2) Can be called from an existing torchrun environment. In this case the grid search
+ must contain only a single config, for the same OOM error reasons as above.
+ The main purpose for this method is to run or debug a single configuration.
+ For a grid search always use the first method.
+
+ Args:
+ config_file_path (Path): The path to the config file.
+ experiment_folder_path (Path): The path to the experiment folder.
+ grid_search (list[GridSearchItem]): The grid search items to be used for the profiler.
+ num_warmup_steps (int): The number of warmup steps to be used for the profiler.
+ During the warmup steps, the profiler is not measuring the memory and runtime.
+ num_measurement_steps (int): The number of measurement steps to be used for the profiler.
+ During the measurement steps, the profiler collects the memory and runtime statistics.
+ nproc_per_node (int, optional): The number of processes (ranks) to be used per node. Defaults to 1.
+ num_nodes (int, optional): The number of nodes to be used. Defaults to 1.
+ node_rank (int, optional): The rank of the current node. Defaults to 0.
+ rdzv_endpoint: str, optional): The rendezvous endpoint to be used. Defaults to "localhost:0",
+ in which case torchrun selects a free empty port on localhost itself.
+
+ Raises:
+ RuntimeError: If the profiler is called from a torchrun process with multiple configs.
+ The profiler can only be called via torchrun if the grid search has a length of 1.
+ RuntimeError: If the profiler is not started from a torchrun or a python process.
+ """
+ # load the config file
+ with open(config_file_path, "r") as f:
+ config_string = f.read()
+ config_dict = yaml.safe_load(config_string)
+ # get one config for each grid search item
+ config_dicts = GridSearchUtils.get_configs_from_grid_search(
+ config_dict=config_dict,
+ grid_search=grid_search,
+ )
+ # run the profiler for each config
+ if len(config_dicts) > 1 and is_launched_via_torchrun():
+ raise RuntimeError(
+ "TrainStepProfilerStarter.run_train_step_profiler() must not be called via torchrun "
+ "with multiple configs. The reason is that recovering from OOM errors is not possible "
+ "and the processes need to be killed and restarted."
+ )
+ for config_dict in tqdm.tqdm(config_dicts):
+ with tempfile.NamedTemporaryFile("w+") as temp_file:
+ yaml.dump(config_dict, temp_file)
+ temp_file_path = temp_file.name
+ # TODO call subprocdess here with torchrun command
+ if not is_launched_via_torchrun():
+ full_main_path = Path(__main__.__file__).resolve()
+ torch_run_args = [
+ "--nproc_per_node",
+ str(nproc_per_node),
+ "--nnodes",
+ str(num_nodes),
+ "--node_rank",
+ str(node_rank),
+ "--rdzv_backend",
+ "c10d",
+ "--rdzv_endpoint",
+ rdzv_endpoint,
+ ]
+ modalities_args = [
+ str(full_main_path),
+ "profile",
+ "train_step",
+ "--config_file_path",
+ str(temp_file_path),
+ "--experiment_folder_path",
+ str(experiment_folder_path),
+ "--num_measurement_steps",
+ str(num_measurement_steps),
+ "--num_warmup_steps",
+ str(num_warmup_steps),
+ ]
+ run_torchrun_with_cleanup(torch_run_args=torch_run_args, script_args=modalities_args)
+ elif is_launched_via_torchrun():
+ ModalitiesProfiler.get_train_step_statistics(
+ config_file_path=temp_file_path,
+ num_warmup_steps=num_warmup_steps,
+ num_measurement_steps=num_measurement_steps,
+ experiment_folder_path=experiment_folder_path,
+ )
+ else:
+ raise RuntimeError(
+ "TrainStepProfilerStarter.run_train_step_profiler() must not be called from a torchrun process."
+ )
+
+ @staticmethod
+ def get_forward_pass_profiling(
+ num_measurements: int, config_file_path: Path, profiler_activities: list[ProfilerActivity] = None
+ ) -> profile:
+ if profiler_activities is None:
+ profiler_activities = [ProfilerActivity.CUDA]
+
+ profiler_context_manager = profile(
+ activities=profiler_activities,
+ schedule=schedule(wait=2, warmup=2, active=num_measurements),
+ record_shapes=True,
+ profile_memory=True,
+ with_flops=True,
+ with_stack=True,
+ with_modules=True,
+ )
+ ModalitiesProfiler.get_forward_pass_profiling(
+ config_file_path=config_file_path,
+ num_measurement_steps=num_measurements,
+ profile_context_manager=profiler_context_manager,
+ )
+ return profiler_context_manager
diff --git a/src/modalities/utils/run_torchrun_script.py b/src/modalities/utils/run_torchrun_script.py
new file mode 100644
index 000000000..50ff4a1fc
--- /dev/null
+++ b/src/modalities/utils/run_torchrun_script.py
@@ -0,0 +1,62 @@
+import os
+import signal
+import subprocess
+import time
+
+
+def run_torchrun_with_cleanup(torch_run_args: list[str], script_args: list[str]):
+ """Starts a script with torchrun and cleans up the process group on exit.
+ While for training, it is advised to run torchrun directly in the command line,
+ this function is useful for profiling a set of configs with torchrun, as it
+ allows to run each config of a grid search in a separate torchrun environment
+ with a subsequent cleanup of the process group.
+
+ Note that the process group is killed regardless of the exit code of the script to
+ enforce that all processes are stopped, no zombies are left behind and all GPU memory
+ gets released. A less aggressive cleanup did not release the GPU memory in some cases.
+
+ With CTRL+C the process group can be killed directly by the user.
+
+ Example torchrun single node command args on 4 ranks:
+ ["--nproc_per_node", "4",
+ "--nnodes", "1",
+ "--node_rank", "0",
+ "--rdzv_id", "0",
+ "--rdzv_backend", "c10d",
+ "--rdzv_endpoint", "localhost:0"]
+
+ Args:
+ torch_run_args (list[str]): The arguments to pass to torchrun.
+ script_args (list[str]): The script path and its arguments.
+ """
+
+ torch_run = ["torchrun", *torch_run_args]
+
+ print("[Launcher] Starting torchrun...")
+ print(f"[Launcher] Command: {' '.join(torch_run)} {' '.join(script_args)}")
+ proc = subprocess.Popen([*torch_run, *script_args], preexec_fn=os.setsid) # start a new process group
+
+ try:
+ proc.wait()
+ print("[Launcher] torchrun exited. Forcing cleanup of process group...")
+
+ # Always kill process group regardless of exit code
+ try:
+ # more graceful, allowing process to cleanup cleanup
+ os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
+ time.sleep(2)
+ # immediate, forceful killing the process without cleanup
+ os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
+ except ProcessLookupError:
+ print("[Launcher] Process group already exited.")
+ except Exception as e:
+ print(f"[Launcher] Failed to kill process group: {e}")
+ except KeyboardInterrupt:
+ print("[Launcher] Interrupted. Killing process group...")
+ try:
+ os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
+ time.sleep(2)
+ os.killpg(os.getpgid(proc.pid), signal.SIGKILL)
+ except Exception as e:
+ print(f"[Launcher] Error while handling KeyboardInterrupt: {e}")
+ raise
diff --git a/tests/end2end_tests/test_utils.py b/tests/end2end_tests/test_utils.py
index 46195a9c5..27f1412e6 100644
--- a/tests/end2end_tests/test_utils.py
+++ b/tests/end2end_tests/test_utils.py
@@ -12,7 +12,7 @@
from modalities.config.config import ProcessGroupBackendType
from modalities.config.pydantic_if_types import PydanticAppStateType
from modalities.util import get_total_number_of_trainable_parameters
-from modalities.utils.typing import FSDPX
+from modalities.utils.typing_utils import FSDPX
from tests.end2end_tests.custom_components import MultiProcessingCudaEnv
diff --git a/tests/test_torch_compile.py b/tests/test_torch_compile.py
index 5d9ee5c88..fab2ed217 100644
--- a/tests/test_torch_compile.py
+++ b/tests/test_torch_compile.py
@@ -77,8 +77,9 @@ def test_get_compiled_model_no_matching_blocks(gpt2_model):
"""
Test that get_compiled_model raises a ValueError if no blocks match the specified types.
"""
- with pytest.raises(ValueError, match="None of the provided block_names match any modules in the model"):
- ModelFactory.get_compiled_model(gpt2_model, block_names=["Conv2d"], fullgraph=True)
+ block_name = "Conv2d"
+ with pytest.raises(ValueError, match=f"The block name {block_name} does not match any modules in the model"):
+ ModelFactory.get_compiled_model(gpt2_model, block_names=[block_name], fullgraph=True)
def test_get_compiled_model_empty_block_names(gpt2_model):
diff --git a/tests/training/config_activation_checkpointing.yaml b/tests/training/config_activation_checkpointing.yaml
index 134c59e4d..53e1b2a14 100644
--- a/tests/training/config_activation_checkpointing.yaml
+++ b/tests/training/config_activation_checkpointing.yaml
@@ -29,6 +29,9 @@ selective_op_activation_checkpointed_model:
instance_key: model_raw
pass_type: BY_REFERENCE
layers_fqn: transformer.h
+ sac_fun_params:
+ save_ops_keys:
+ - torch.ops.aten.mm.default
model_raw:
component_key: model
diff --git a/tests/utils/test_experiment_id_generation.py b/tests/utils/test_experiment_id_generation.py
index 272bb9f10..5573cce31 100644
--- a/tests/utils/test_experiment_id_generation.py
+++ b/tests/utils/test_experiment_id_generation.py
@@ -7,7 +7,7 @@
import torch.multiprocessing as mp
from modalities.config.config import ProcessGroupBackendType
-from modalities.util import get_experiment_id_of_run
+from modalities.util import get_synced_experiment_id_of_run
from tests.end2end_tests.custom_components import MultiProcessingCudaEnv
@@ -45,7 +45,7 @@ def _run_experiment_id_generation_test_in_dist_env(
world_size=world_size,
rdvz_port=rdvz_port,
):
- experiment_id = get_experiment_id_of_run(
+ experiment_id = get_synced_experiment_id_of_run(
config_file_path=config_file_path,
hash_length=8,
max_experiment_id_byte_length=1024,
diff --git a/tutorials/profiling/activation_checkpointing_profiling.py b/tutorials/profiling/activation_checkpointing_profiling.py
new file mode 100644
index 000000000..d5c075a23
--- /dev/null
+++ b/tutorials/profiling/activation_checkpointing_profiling.py
@@ -0,0 +1,39 @@
+from pathlib import Path
+
+from modalities.util import get_experiment_id_from_config
+from modalities.utils.profilers.grid_search_utils import GridSearchItem
+from modalities.utils.profilers.profiler_starters import ModalitiesProfilerStarter
+
+if __name__ == "__main__":
+ current_dir = Path(__file__).resolve().parent
+ config_file_path = current_dir / "config_activation_checkpointing_fsdp2_benchmark_8B.yaml"
+
+ experiment_folder_path = current_dir / "experiments"
+ experiment_id = get_experiment_id_from_config(config_file_path)
+
+ grid_search = [
+ GridSearchItem(name="settings.benchmark.batch_size", values=list(range(1, 10))),
+ GridSearchItem(name="settings.benchmark.sequence_length", values=[4096]),
+ GridSearchItem(name="settings.benchmark.vocab_size", values=[50304]),
+ GridSearchItem(
+ name="settings.benchmark.ac_ops_keys",
+ values=[
+ [],
+ ["torch.ops.aten.mm.default"],
+ ["torch.ops.aten._scaled_dot_product_efficient_attention.default"],
+ ["torch.ops.aten._scaled_dot_product_flash_attention.default"],
+ ["torch.ops._c10d_functional.reduce_scatter_tensor.default"],
+ ["torch.ops.aten.max.default"],
+ ],
+ ),
+ ]
+ ModalitiesProfilerStarter.run_train_step_profiler(
+ config_file_path=config_file_path,
+ experiment_folder_path=experiment_folder_path / experiment_id,
+ grid_search=grid_search,
+ num_warmup_steps=2,
+ num_measurement_steps=5,
+ nproc_per_node=8,
+ num_nodes=1,
+ rdzv_endpoint="localhost:0",
+ )
diff --git a/tutorials/profiling/aten_ops_profilling.py b/tutorials/profiling/aten_ops_profilling.py
new file mode 100644
index 000000000..83955093e
--- /dev/null
+++ b/tutorials/profiling/aten_ops_profilling.py
@@ -0,0 +1,55 @@
+import os
+from pathlib import Path
+
+from torch.profiler import ProfilerActivity
+
+from modalities.utils.profilers.profiler_starters import ModalitiesProfilerStarter
+
+if __name__ == "__main__":
+ current_dir = Path(__file__).resolve().parent
+ config_file_path = current_dir / "config_activation_checkpointing_fsdp2_benchmark_small.yaml"
+
+ num_measurements = 10
+ profiler = ModalitiesProfilerStarter.get_forward_pass_profiling(
+ num_measurements=num_measurements,
+ config_file_path=config_file_path,
+ profiler_activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA],
+ )
+
+ print(
+ profiler.key_averages().table(
+ sort_by="self_cuda_time_total",
+ # row_limit=row_limit,
+ max_name_column_width=240,
+ )
+ )
+ if int(os.environ["RANK"]) == 0:
+ profiler.export_chrome_trace(os.path.join(config_file_path.parent, "activation_checkpointing_profile.json"))
+
+ pass
+
+
+# # Now, access recorded function events
+# # 3. AFTER the "with" closes, THEN inspect!
+
+# if int(os.environ["RANK"]) == 0:
+# events = profiler.events() # <-- only now!
+
+# aten_to_module = []
+
+# for evt in events:
+# if evt.name.startswith("aten::"):
+# module = None
+# if evt.stack:
+# for frame in evt.stack:
+# if 'forward' in frame.name:
+# module = frame.name
+# break
+# aten_to_module.append((evt.name, module))
+
+# print(f"Found {len(aten_to_module)} ATen ops!")
+# for aten, module in aten_to_module:
+# if module is not None:
+# print(f"ATen: {aten:30s} --> Module: {module}")
+
+# pass
diff --git a/tutorials/profiling/config_activation_checkpointing_fsdp2_benchmark_8B.yaml b/tutorials/profiling/config_activation_checkpointing_fsdp2_benchmark_8B.yaml
new file mode 100644
index 000000000..ab20e385a
--- /dev/null
+++ b/tutorials/profiling/config_activation_checkpointing_fsdp2_benchmark_8B.yaml
@@ -0,0 +1,137 @@
+settings:
+ referencing_keys:
+ sample_key: input_ids
+ target_key: target_ids
+ prediction_key: logits
+ benchmark:
+ sequence_length: 4096
+ vocab_size: 50304
+ ac_ops_keys:
+ - torch.ops.aten.mm.default
+ batch_size: 1
+
+initialized_model:
+ component_key: model
+ variant_key: model_initialized
+ config:
+ model:
+ instance_key: fsdp_model
+ pass_type: BY_REFERENCE
+ model_initializer:
+ component_key: model_initialization
+ variant_key: composed
+ config:
+ model_type: gpt2
+ weight_init_type: scaled
+ mean: 0.0
+ std: 0.02
+ num_layers: ${model_raw.config.n_layer}
+
+fsdp_model:
+ component_key: model
+ variant_key: fsdp2_wrapped
+ config:
+ model:
+ instance_key: selective_op_activation_checkpointed_model
+ pass_type: BY_REFERENCE
+ device_mesh:
+ instance_key: device_mesh
+ pass_type: BY_REFERENCE
+ mixed_precision_settings:
+ param_dtype: BF_16
+ reduce_dtype: BF_16
+ block_names: [GPT2Block]
+
+selective_op_activation_checkpointed_model:
+ component_key: model
+ variant_key: selective_activation_checkpointed
+ config:
+ sac_variant: selective_op_activation_checkpointing
+ model:
+ instance_key: model_raw
+ pass_type: BY_REFERENCE
+ layers_fqn: transformer.h
+ sac_fun_params:
+ save_ops_keys: ${settings.benchmark.ac_ops_keys}
+
+model_raw:
+ component_key: model
+ variant_key: gpt2
+ config:
+ use_meta_device: true
+ sample_key: ${settings.referencing_keys.sample_key}
+ poe_type: NOPE
+ sequence_length: ${settings.benchmark.sequence_length}
+ prediction_key: ${loss_fn.config.prediction_key}
+ vocab_size: ${settings.benchmark.vocab_size}
+ n_layer: 32
+ n_head_q: 32
+ n_head_kv: 8
+ ffn_hidden: 21248
+ n_embd: 4096
+ dropout: 0.0
+ bias: false
+ attention_config:
+ qkv_transforms:
+ - type_hint: RotaryTransform
+ config:
+ n_embd: ${model_raw.config.n_embd}
+ n_head: ${model_raw.config.n_head_q}
+ seq_length_dim: -2
+ base_freq: 500000
+ attention_implementation: manual
+ activation_type: swiglu
+ attention_norm_config:
+ norm_type: layer_norm
+ config:
+ normalized_shape: ${model_raw.config.n_embd}
+ eps: 1.0e-05
+ ffn_norm_config:
+ norm_type: layer_norm
+ config:
+ normalized_shape: ${model_raw.config.n_embd}
+ eps: 1.0e-05
+ lm_head_norm_config:
+ norm_type: layer_norm
+ config:
+ normalized_shape: ${model_raw.config.n_embd}
+ eps: 1.0e-05
+ use_weight_tying: true
+
+device_mesh:
+ component_key: device_mesh
+ variant_key: default
+ config:
+ device_type: cuda
+ data_parallel_replicate_degree: 1
+ data_parallel_shard_degree: ${cuda_env:WORLD_SIZE} # i.e., fully sharded
+ world_size: ${cuda_env:WORLD_SIZE}
+
+loss_fn:
+ component_key: loss
+ variant_key: clm_cross_entropy_loss
+ config:
+ target_key: ${settings.referencing_keys.target_key}
+ prediction_key: ${settings.referencing_keys.prediction_key}
+
+
+optimizer:
+ component_key: optimizer
+ variant_key: adam_w
+ config:
+ lr: 0.0001
+ betas: [0.9, 0.95]
+ eps: 1e-8
+ weight_decay: 1e-1
+ weight_decay_groups_excluded: [embedding, layernorm]
+ wrapped_model:
+ instance_key: initialized_model
+ pass_type: BY_REFERENCE
+
+dataset_batch_generator:
+ component_key: dataset_batch_generator
+ variant_key: random
+ config:
+ vocab_size: ${settings.benchmark.vocab_size}
+ sequence_length: ${settings.benchmark.sequence_length}
+ batch_size: ${settings.benchmark.batch_size}
\ No newline at end of file
diff --git a/tutorials/profiling/config_activation_checkpointing_fsdp2_benchmark_small.yaml b/tutorials/profiling/config_activation_checkpointing_fsdp2_benchmark_small.yaml
new file mode 100644
index 000000000..0fdacdfd8
--- /dev/null
+++ b/tutorials/profiling/config_activation_checkpointing_fsdp2_benchmark_small.yaml
@@ -0,0 +1,140 @@
+settings:
+ referencing_keys:
+ sample_key: input_ids
+ target_key: target_ids
+ prediction_key: logits
+ benchmark:
+ sequence_length: 4096
+ vocab_size: 50304
+ ac_ops_keys:
+ - torch.ops.aten.mm.default
+ batch_size: 1
+
+initialized_model:
+ component_key: model
+ variant_key: model_initialized
+ config:
+ model:
+ instance_key: fsdp_model
+ pass_type: BY_REFERENCE
+ model_initializer:
+ component_key: model_initialization
+ variant_key: composed
+ config:
+ model_type: gpt2
+ weight_init_type: scaled
+ mean: 0.0
+ std: 0.02
+ num_layers: ${model_raw.config.n_layer}
+
+fsdp_model:
+ component_key: model
+ variant_key: fsdp2_wrapped
+ config:
+ model:
+ instance_key: selective_op_activation_checkpointed_model
+ pass_type: BY_REFERENCE
+ device_mesh:
+ instance_key: device_mesh
+ pass_type: BY_REFERENCE
+ mixed_precision_settings:
+ param_dtype: BF_16
+ reduce_dtype: BF_16
+ block_names: [GPT2Block]
+
+selective_op_activation_checkpointed_model:
+ component_key: model
+ variant_key: selective_activation_checkpointed
+ config:
+ sac_variant: selective_op_activation_checkpointing
+ model:
+ instance_key: model_raw
+ pass_type: BY_REFERENCE
+ layers_fqn: transformer.h
+ sac_fun_params:
+ save_ops_keys: ${settings.benchmark.ac_ops_keys}
+
+model_raw:
+ component_key: model
+ variant_key: gpt2
+ config:
+ sample_key: input_ids
+ poe_type: NOPE
+ sequence_length: 4096
+ prediction_key: logits
+ vocab_size: 50304 # GPT-2 vocab_size of 50257, padded up to nearest multiple of 64 for efficiency
+ n_layer: 20
+ n_head_q: 8
+ n_head_kv: 8
+ ffn_hidden: 128
+ n_embd: 128
+ dropout: 0.0
+ bias: true # True: bias in Linears and LayerNorms, like GPT-2. False: a bit better and faster
+ attention_config:
+ qkv_transforms:
+ - type_hint: RotaryTransform
+ config:
+ n_embd: ${model_raw.config.n_embd}
+ n_head: ${model_raw.config.n_head_q} #it has to be head_q here
+ seq_length_dim: -2
+ base_freq: 10000
+ attention_implementation: pytorch_flash
+ activation_type: gelu
+ attention_norm_config:
+ norm_type: rms_norm
+ config:
+ ndim: ${model_raw.config.n_embd}
+ bias: true
+ epsilon: 1e-5
+ ffn_norm_config:
+ norm_type: rms_norm
+ config:
+ ndim: ${model_raw.config.n_embd}
+ bias: true
+ epsilon: 1e-5
+ lm_head_norm_config:
+ norm_type: rms_norm
+ config:
+ ndim: ${model_raw.config.n_embd}
+ bias: true
+ epsilon: 1e-5
+ use_weight_tying: true
+ use_meta_device: false
+
+device_mesh:
+ component_key: device_mesh
+ variant_key: default
+ config:
+ device_type: cuda
+ data_parallel_replicate_degree: 1
+ data_parallel_shard_degree: ${cuda_env:WORLD_SIZE} # i.e., fully sharded
+ world_size: ${cuda_env:WORLD_SIZE}
+
+loss_fn:
+ component_key: loss
+ variant_key: clm_cross_entropy_loss
+ config:
+ target_key: ${settings.referencing_keys.target_key}
+ prediction_key: ${settings.referencing_keys.prediction_key}
+
+
+optimizer:
+ component_key: optimizer
+ variant_key: adam_w
+ config:
+ lr: 0.0001
+ betas: [0.9, 0.95]
+ eps: 1e-8
+ weight_decay: 1e-1
+ weight_decay_groups_excluded: [embedding, layernorm]
+ wrapped_model:
+ instance_key: initialized_model
+ pass_type: BY_REFERENCE
+
+dataset_batch_generator:
+ component_key: dataset_batch_generator
+ variant_key: random
+ config:
+ vocab_size: ${settings.benchmark.vocab_size}
+ sequence_length: ${settings.benchmark.sequence_length}
+ batch_size: ${settings.benchmark.batch_size}
\ No newline at end of file
diff --git a/tutorials/profiling/profiling_logs_analysis.ipynb b/tutorials/profiling/profiling_logs_analysis.ipynb
new file mode 100644
index 000000000..51ad015b1
--- /dev/null
+++ b/tutorials/profiling/profiling_logs_analysis.ipynb
@@ -0,0 +1,1242 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "from modalities.utils.profilers.profile_logs_analyzers import ProfileLogsAnalyzer\n",
+ "from pathlib import Path"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "log_dirs = {\n",
+ " \"FSDP2\": Path(\"/raid/s3/opengptx/max_lue/repositories/modalities/tutorials/profiling/experiments/2025-04-28__21-55-30_890b7ede\"), \n",
+ " # \"compile\": Path(\"/raid/s3/opengptx/max_lue/repositories/modalities/tests/training/benchmark/2025-04-25__01-13-08_ed5e5044\")\n",
+ "}\n",
+ "results_dict = {}\n",
+ "for name, log_dir in log_dirs.items():\n",
+ " results = ProfileLogsAnalyzer.load_profiling_logs(log_dir)\n",
+ " df = ProfileLogsAnalyzer.to_pandas_df(results)\n",
+ " df[\"total_step_time\"] = df[\"forward_time\"] + df[\"backward_time\"] + df[\"step_time\"]\n",
+ " df.sort_values(by=[\"total_step_time\"], inplace=True, ascending=True)\n",
+ " df[\"error\"] = df[\"error\"].apply(lambda x: x[:20])\n",
+ " results_dict[name] = df\n",
+ " df[\"ac_ops_keys\"] = df[\"ac_ops_keys\"].apply(lambda x: \" \".join(x))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def filter_df(df):\n",
+ " df_filtered = df.groupby(by=[\"ac_ops_keys\", \"batch_size\"]).first().reset_index()\n",
+ " df_filtered = df_filtered[df_filtered[\"error\"] == \"\"]\n",
+ " return df_filtered\n",
+ "\n",
+ "results_dict = {\n",
+ " name: filter_df(df) for name, df in results_dict.items()\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " name | \n",
+ " ac_ops_keys | \n",
+ " batch_size | \n",
+ " sequence_length | \n",
+ " vocab_size | \n",
+ " local_rank | \n",
+ " global_rank | \n",
+ " num_ranks | \n",
+ " hostname | \n",
+ " peak_memory | \n",
+ " forward_time | \n",
+ " backward_time | \n",
+ " step_time | \n",
+ " error | \n",
+ " total_step_time | \n",
+ " lines | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " | 0 | \n",
+ " FSDP2 | \n",
+ " | \n",
+ " 1 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 70597.919434 | \n",
+ " 0.124337 | \n",
+ " 0.980498 | \n",
+ " 0.161218 | \n",
+ " | \n",
+ " 1.266053 | \n",
+ " FSDP2_ | \n",
+ "
\n",
+ " \n",
+ " | 9 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 1 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 20596.247559 | \n",
+ " 0.172272 | \n",
+ " 1.455008 | \n",
+ " 0.153634 | \n",
+ " | \n",
+ " 1.780915 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 10 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 2 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 25308.341309 | \n",
+ " 0.116002 | \n",
+ " 1.453387 | \n",
+ " 0.131507 | \n",
+ " | \n",
+ " 1.700896 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 11 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 3 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 30023.435059 | \n",
+ " 0.136192 | \n",
+ " 1.404441 | \n",
+ " 0.139726 | \n",
+ " | \n",
+ " 1.680359 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 12 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 4 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 35430.302246 | \n",
+ " 0.133111 | \n",
+ " 1.383679 | \n",
+ " 0.138043 | \n",
+ " | \n",
+ " 1.654834 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 13 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 5 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 41072.395996 | \n",
+ " 0.173290 | \n",
+ " 1.382391 | \n",
+ " 0.121789 | \n",
+ " | \n",
+ " 1.677471 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 14 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 6 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 46712.489746 | \n",
+ " 0.173713 | \n",
+ " 1.381481 | \n",
+ " 0.121541 | \n",
+ " | \n",
+ " 1.676735 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 15 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 7 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 52353.583496 | \n",
+ " 0.172224 | \n",
+ " 1.385767 | \n",
+ " 0.120974 | \n",
+ " | \n",
+ " 1.678965 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 16 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 8 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 57994.677246 | \n",
+ " 0.172124 | \n",
+ " 1.381862 | \n",
+ " 0.120619 | \n",
+ " | \n",
+ " 1.674605 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 17 | \n",
+ " FSDP2 | \n",
+ " torch.ops._c10d_functional.reduce_scatter_tens... | \n",
+ " 9 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 63635.770996 | \n",
+ " 0.231725 | \n",
+ " 1.361712 | \n",
+ " 0.114032 | \n",
+ " | \n",
+ " 1.707468 | \n",
+ " FSDP2_torch.ops._c10d_functional.reduce_scatte... | \n",
+ "
\n",
+ " \n",
+ " | 18 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 1 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 20596.247559 | \n",
+ " 0.172914 | \n",
+ " 1.447478 | \n",
+ " 0.152831 | \n",
+ " | \n",
+ " 1.773222 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 19 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 2 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 25308.341309 | \n",
+ " 0.115029 | \n",
+ " 1.451886 | \n",
+ " 0.131590 | \n",
+ " | \n",
+ " 1.698505 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 20 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 3 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 30023.435059 | \n",
+ " 0.136032 | \n",
+ " 1.405333 | \n",
+ " 0.140035 | \n",
+ " | \n",
+ " 1.681400 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 21 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 4 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 35430.302246 | \n",
+ " 0.133929 | \n",
+ " 1.384165 | \n",
+ " 0.137633 | \n",
+ " | \n",
+ " 1.655726 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 22 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 5 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 41072.395996 | \n",
+ " 0.172719 | \n",
+ " 1.383666 | \n",
+ " 0.122034 | \n",
+ " | \n",
+ " 1.678419 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 23 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 6 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 46712.489746 | \n",
+ " 0.173746 | \n",
+ " 1.381417 | \n",
+ " 0.121462 | \n",
+ " | \n",
+ " 1.676625 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 24 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 7 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 52353.583496 | \n",
+ " 0.172683 | \n",
+ " 1.385654 | \n",
+ " 0.120812 | \n",
+ " | \n",
+ " 1.679150 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 25 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 8 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 57994.677246 | \n",
+ " 0.171448 | \n",
+ " 1.380915 | \n",
+ " 0.120470 | \n",
+ " | \n",
+ " 1.672834 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 26 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_efficient_a... | \n",
+ " 9 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 63635.770996 | \n",
+ " 0.231046 | \n",
+ " 1.361752 | \n",
+ " 0.114048 | \n",
+ " | \n",
+ " 1.706845 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_effic... | \n",
+ "
\n",
+ " \n",
+ " | 27 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 1 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 20596.247559 | \n",
+ " 0.170201 | \n",
+ " 1.454882 | \n",
+ " 0.153355 | \n",
+ " | \n",
+ " 1.778438 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 28 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 2 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 25308.341309 | \n",
+ " 0.115838 | \n",
+ " 1.450299 | \n",
+ " 0.131219 | \n",
+ " | \n",
+ " 1.697356 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 29 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 3 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 30023.435059 | \n",
+ " 0.137594 | \n",
+ " 1.406143 | \n",
+ " 0.140352 | \n",
+ " | \n",
+ " 1.684089 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 30 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 4 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 35430.302246 | \n",
+ " 0.133291 | \n",
+ " 1.382759 | \n",
+ " 0.137890 | \n",
+ " | \n",
+ " 1.653940 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 31 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 5 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 41072.395996 | \n",
+ " 0.172723 | \n",
+ " 1.381461 | \n",
+ " 0.121777 | \n",
+ " | \n",
+ " 1.675961 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 32 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 6 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 46712.489746 | \n",
+ " 0.172171 | \n",
+ " 1.381228 | \n",
+ " 0.121580 | \n",
+ " | \n",
+ " 1.674979 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 33 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 7 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 52353.583496 | \n",
+ " 0.172835 | \n",
+ " 1.387003 | \n",
+ " 0.121044 | \n",
+ " | \n",
+ " 1.680882 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 34 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 8 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 57994.677246 | \n",
+ " 0.172543 | \n",
+ " 1.382412 | \n",
+ " 0.120486 | \n",
+ " | \n",
+ " 1.675441 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 35 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten._scaled_dot_product_flash_atten... | \n",
+ " 9 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 63635.770996 | \n",
+ " 0.231598 | \n",
+ " 1.360831 | \n",
+ " 0.113972 | \n",
+ " | \n",
+ " 1.706401 | \n",
+ " FSDP2_torch.ops.aten._scaled_dot_product_flash... | \n",
+ "
\n",
+ " \n",
+ " | 36 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 1 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 20596.247559 | \n",
+ " 0.167773 | \n",
+ " 1.452194 | \n",
+ " 0.153117 | \n",
+ " | \n",
+ " 1.773085 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 37 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 2 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 25308.341309 | \n",
+ " 0.116576 | \n",
+ " 1.454050 | \n",
+ " 0.131568 | \n",
+ " | \n",
+ " 1.702193 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 38 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 3 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 30023.435059 | \n",
+ " 0.136723 | \n",
+ " 1.404551 | \n",
+ " 0.140190 | \n",
+ " | \n",
+ " 1.681463 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 39 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 4 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 35430.302246 | \n",
+ " 0.135040 | \n",
+ " 1.384831 | \n",
+ " 0.137974 | \n",
+ " | \n",
+ " 1.657845 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 40 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 5 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 41072.395996 | \n",
+ " 0.172681 | \n",
+ " 1.382533 | \n",
+ " 0.121719 | \n",
+ " | \n",
+ " 1.676934 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 41 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 6 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 46712.489746 | \n",
+ " 0.172352 | \n",
+ " 1.381127 | \n",
+ " 0.121553 | \n",
+ " | \n",
+ " 1.675032 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 42 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 7 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 52353.583496 | \n",
+ " 0.172609 | \n",
+ " 1.387061 | \n",
+ " 0.120882 | \n",
+ " | \n",
+ " 1.680552 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 43 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 8 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 57994.677246 | \n",
+ " 0.171527 | \n",
+ " 1.382405 | \n",
+ " 0.120440 | \n",
+ " | \n",
+ " 1.674372 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 44 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.max.default | \n",
+ " 9 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 63635.770996 | \n",
+ " 0.231022 | \n",
+ " 1.360587 | \n",
+ " 0.113920 | \n",
+ " | \n",
+ " 1.705529 | \n",
+ " FSDP2_torch.ops.aten.max.default | \n",
+ "
\n",
+ " \n",
+ " | 45 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.mm.default | \n",
+ " 1 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 24060.020996 | \n",
+ " 0.173083 | \n",
+ " 1.363419 | \n",
+ " 0.161739 | \n",
+ " | \n",
+ " 1.698242 | \n",
+ " FSDP2_torch.ops.aten.mm.default | \n",
+ "
\n",
+ " \n",
+ " | 46 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.mm.default | \n",
+ " 2 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 35253.114746 | \n",
+ " 0.115637 | \n",
+ " 1.375836 | \n",
+ " 0.133988 | \n",
+ " | \n",
+ " 1.625462 | \n",
+ " FSDP2_torch.ops.aten.mm.default | \n",
+ "
\n",
+ " \n",
+ " | 47 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.mm.default | \n",
+ " 3 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 46574.169434 | \n",
+ " 0.136447 | \n",
+ " 1.341783 | \n",
+ " 0.120393 | \n",
+ " | \n",
+ " 1.598623 | \n",
+ " FSDP2_torch.ops.aten.mm.default | \n",
+ "
\n",
+ " \n",
+ " | 48 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.mm.default | \n",
+ " 4 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 57982.263184 | \n",
+ " 0.133041 | \n",
+ " 1.325838 | \n",
+ " 0.118611 | \n",
+ " | \n",
+ " 1.577489 | \n",
+ " FSDP2_torch.ops.aten.mm.default | \n",
+ "
\n",
+ " \n",
+ " | 49 | \n",
+ " FSDP2 | \n",
+ " torch.ops.aten.mm.default | \n",
+ " 5 | \n",
+ " 4096 | \n",
+ " 50304 | \n",
+ " 1 | \n",
+ " 1 | \n",
+ " 8 | \n",
+ " dgx2 | \n",
+ " 69392.356934 | \n",
+ " 0.173794 | \n",
+ " 1.308753 | \n",
+ " 0.128471 | \n",
+ " | \n",
+ " 1.611018 | \n",
+ " FSDP2_torch.ops.aten.mm.default | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " name ac_ops_keys batch_size \\\n",
+ "0 FSDP2 1 \n",
+ "9 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 1 \n",
+ "10 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 2 \n",
+ "11 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 3 \n",
+ "12 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 4 \n",
+ "13 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 5 \n",
+ "14 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 6 \n",
+ "15 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 7 \n",
+ "16 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 8 \n",
+ "17 FSDP2 torch.ops._c10d_functional.reduce_scatter_tens... 9 \n",
+ "18 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 1 \n",
+ "19 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 2 \n",
+ "20 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 3 \n",
+ "21 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 4 \n",
+ "22 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 5 \n",
+ "23 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 6 \n",
+ "24 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 7 \n",
+ "25 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 8 \n",
+ "26 FSDP2 torch.ops.aten._scaled_dot_product_efficient_a... 9 \n",
+ "27 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 1 \n",
+ "28 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 2 \n",
+ "29 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 3 \n",
+ "30 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 4 \n",
+ "31 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 5 \n",
+ "32 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 6 \n",
+ "33 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 7 \n",
+ "34 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 8 \n",
+ "35 FSDP2 torch.ops.aten._scaled_dot_product_flash_atten... 9 \n",
+ "36 FSDP2 torch.ops.aten.max.default 1 \n",
+ "37 FSDP2 torch.ops.aten.max.default 2 \n",
+ "38 FSDP2 torch.ops.aten.max.default 3 \n",
+ "39 FSDP2 torch.ops.aten.max.default 4 \n",
+ "40 FSDP2 torch.ops.aten.max.default 5 \n",
+ "41 FSDP2 torch.ops.aten.max.default 6 \n",
+ "42 FSDP2 torch.ops.aten.max.default 7 \n",
+ "43 FSDP2 torch.ops.aten.max.default 8 \n",
+ "44 FSDP2 torch.ops.aten.max.default 9 \n",
+ "45 FSDP2 torch.ops.aten.mm.default 1 \n",
+ "46 FSDP2 torch.ops.aten.mm.default 2 \n",
+ "47 FSDP2 torch.ops.aten.mm.default 3 \n",
+ "48 FSDP2 torch.ops.aten.mm.default 4 \n",
+ "49 FSDP2 torch.ops.aten.mm.default 5 \n",
+ "\n",
+ " sequence_length vocab_size local_rank global_rank num_ranks hostname \\\n",
+ "0 4096 50304 1 1 8 dgx2 \n",
+ "9 4096 50304 1 1 8 dgx2 \n",
+ "10 4096 50304 1 1 8 dgx2 \n",
+ "11 4096 50304 1 1 8 dgx2 \n",
+ "12 4096 50304 1 1 8 dgx2 \n",
+ "13 4096 50304 1 1 8 dgx2 \n",
+ "14 4096 50304 1 1 8 dgx2 \n",
+ "15 4096 50304 1 1 8 dgx2 \n",
+ "16 4096 50304 1 1 8 dgx2 \n",
+ "17 4096 50304 1 1 8 dgx2 \n",
+ "18 4096 50304 1 1 8 dgx2 \n",
+ "19 4096 50304 1 1 8 dgx2 \n",
+ "20 4096 50304 1 1 8 dgx2 \n",
+ "21 4096 50304 1 1 8 dgx2 \n",
+ "22 4096 50304 1 1 8 dgx2 \n",
+ "23 4096 50304 1 1 8 dgx2 \n",
+ "24 4096 50304 1 1 8 dgx2 \n",
+ "25 4096 50304 1 1 8 dgx2 \n",
+ "26 4096 50304 1 1 8 dgx2 \n",
+ "27 4096 50304 1 1 8 dgx2 \n",
+ "28 4096 50304 1 1 8 dgx2 \n",
+ "29 4096 50304 1 1 8 dgx2 \n",
+ "30 4096 50304 1 1 8 dgx2 \n",
+ "31 4096 50304 1 1 8 dgx2 \n",
+ "32 4096 50304 1 1 8 dgx2 \n",
+ "33 4096 50304 1 1 8 dgx2 \n",
+ "34 4096 50304 1 1 8 dgx2 \n",
+ "35 4096 50304 1 1 8 dgx2 \n",
+ "36 4096 50304 1 1 8 dgx2 \n",
+ "37 4096 50304 1 1 8 dgx2 \n",
+ "38 4096 50304 1 1 8 dgx2 \n",
+ "39 4096 50304 1 1 8 dgx2 \n",
+ "40 4096 50304 1 1 8 dgx2 \n",
+ "41 4096 50304 1 1 8 dgx2 \n",
+ "42 4096 50304 1 1 8 dgx2 \n",
+ "43 4096 50304 1 1 8 dgx2 \n",
+ "44 4096 50304 1 1 8 dgx2 \n",
+ "45 4096 50304 1 1 8 dgx2 \n",
+ "46 4096 50304 1 1 8 dgx2 \n",
+ "47 4096 50304 1 1 8 dgx2 \n",
+ "48 4096 50304 1 1 8 dgx2 \n",
+ "49 4096 50304 1 1 8 dgx2 \n",
+ "\n",
+ " peak_memory forward_time backward_time step_time error \\\n",
+ "0 70597.919434 0.124337 0.980498 0.161218 \n",
+ "9 20596.247559 0.172272 1.455008 0.153634 \n",
+ "10 25308.341309 0.116002 1.453387 0.131507 \n",
+ "11 30023.435059 0.136192 1.404441 0.139726 \n",
+ "12 35430.302246 0.133111 1.383679 0.138043 \n",
+ "13 41072.395996 0.173290 1.382391 0.121789 \n",
+ "14 46712.489746 0.173713 1.381481 0.121541 \n",
+ "15 52353.583496 0.172224 1.385767 0.120974 \n",
+ "16 57994.677246 0.172124 1.381862 0.120619 \n",
+ "17 63635.770996 0.231725 1.361712 0.114032 \n",
+ "18 20596.247559 0.172914 1.447478 0.152831 \n",
+ "19 25308.341309 0.115029 1.451886 0.131590 \n",
+ "20 30023.435059 0.136032 1.405333 0.140035 \n",
+ "21 35430.302246 0.133929 1.384165 0.137633 \n",
+ "22 41072.395996 0.172719 1.383666 0.122034 \n",
+ "23 46712.489746 0.173746 1.381417 0.121462 \n",
+ "24 52353.583496 0.172683 1.385654 0.120812 \n",
+ "25 57994.677246 0.171448 1.380915 0.120470 \n",
+ "26 63635.770996 0.231046 1.361752 0.114048 \n",
+ "27 20596.247559 0.170201 1.454882 0.153355 \n",
+ "28 25308.341309 0.115838 1.450299 0.131219 \n",
+ "29 30023.435059 0.137594 1.406143 0.140352 \n",
+ "30 35430.302246 0.133291 1.382759 0.137890 \n",
+ "31 41072.395996 0.172723 1.381461 0.121777 \n",
+ "32 46712.489746 0.172171 1.381228 0.121580 \n",
+ "33 52353.583496 0.172835 1.387003 0.121044 \n",
+ "34 57994.677246 0.172543 1.382412 0.120486 \n",
+ "35 63635.770996 0.231598 1.360831 0.113972 \n",
+ "36 20596.247559 0.167773 1.452194 0.153117 \n",
+ "37 25308.341309 0.116576 1.454050 0.131568 \n",
+ "38 30023.435059 0.136723 1.404551 0.140190 \n",
+ "39 35430.302246 0.135040 1.384831 0.137974 \n",
+ "40 41072.395996 0.172681 1.382533 0.121719 \n",
+ "41 46712.489746 0.172352 1.381127 0.121553 \n",
+ "42 52353.583496 0.172609 1.387061 0.120882 \n",
+ "43 57994.677246 0.171527 1.382405 0.120440 \n",
+ "44 63635.770996 0.231022 1.360587 0.113920 \n",
+ "45 24060.020996 0.173083 1.363419 0.161739 \n",
+ "46 35253.114746 0.115637 1.375836 0.133988 \n",
+ "47 46574.169434 0.136447 1.341783 0.120393 \n",
+ "48 57982.263184 0.133041 1.325838 0.118611 \n",
+ "49 69392.356934 0.173794 1.308753 0.128471 \n",
+ "\n",
+ " total_step_time lines \n",
+ "0 1.266053 FSDP2_ \n",
+ "9 1.780915 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "10 1.700896 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "11 1.680359 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "12 1.654834 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "13 1.677471 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "14 1.676735 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "15 1.678965 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "16 1.674605 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "17 1.707468 FSDP2_torch.ops._c10d_functional.reduce_scatte... \n",
+ "18 1.773222 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "19 1.698505 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "20 1.681400 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "21 1.655726 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "22 1.678419 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "23 1.676625 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "24 1.679150 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "25 1.672834 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "26 1.706845 FSDP2_torch.ops.aten._scaled_dot_product_effic... \n",
+ "27 1.778438 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "28 1.697356 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "29 1.684089 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "30 1.653940 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "31 1.675961 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "32 1.674979 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "33 1.680882 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "34 1.675441 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "35 1.706401 FSDP2_torch.ops.aten._scaled_dot_product_flash... \n",
+ "36 1.773085 FSDP2_torch.ops.aten.max.default \n",
+ "37 1.702193 FSDP2_torch.ops.aten.max.default \n",
+ "38 1.681463 FSDP2_torch.ops.aten.max.default \n",
+ "39 1.657845 FSDP2_torch.ops.aten.max.default \n",
+ "40 1.676934 FSDP2_torch.ops.aten.max.default \n",
+ "41 1.675032 FSDP2_torch.ops.aten.max.default \n",
+ "42 1.680552 FSDP2_torch.ops.aten.max.default \n",
+ "43 1.674372 FSDP2_torch.ops.aten.max.default \n",
+ "44 1.705529 FSDP2_torch.ops.aten.max.default \n",
+ "45 1.698242 FSDP2_torch.ops.aten.mm.default \n",
+ "46 1.625462 FSDP2_torch.ops.aten.mm.default \n",
+ "47 1.598623 FSDP2_torch.ops.aten.mm.default \n",
+ "48 1.577489 FSDP2_torch.ops.aten.mm.default \n",
+ "49 1.611018 FSDP2_torch.ops.aten.mm.default "
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "def combine_dfs(result_dict: dict[str, pd.DataFrame]) -> pd.DataFrame:\n",
+ " combined_df = pd.concat(result_dict.values(), keys=result_dict.keys())\n",
+ " combined_df.reset_index(level=0, inplace=True)\n",
+ " combined_df.rename(columns={\"level_0\": \"name\"}, inplace=True)\n",
+ " return combined_df\n",
+ "\n",
+ "combined_df = combine_dfs(results_dict)\n",
+ "combined_df[\"lines\"] = combined_df[\"name\"] + \"_\" + combined_df[\"ac_ops_keys\"]\n",
+ "combined_df"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3Xd8VfXh//HXufveJDc7YQQCJGHvoVVBwIGCddS6926rtbW29ve1/X5rrXaora3VuuoWR2vV1larouJGZYMgEPYKCZk3yb258/P74yaBkDAFEuD9fDzu49575udcTkLe97MsY4xBRERERERERPY7W2cXQERERERERORwpdAtIiIiIiIicoAodIuIiIiIiIgcIArdIiIiIiIiIgeIQreIiIiIiIjIAaLQLSIiIiIiInKAKHSLiIiIiIiIHCAK3SIiIiIiIiIHiEK3iIiIiIiIyAGi0C0icgh5//33sSyL999/v7OLctBdccUV9OnTp7OLcUR66qmnsCyLOXPmdHZRDkv6fA+MSZMmMWnSpM4uhoiIQreIyO5YlrVHjz0Jwr/5zW/45z//ecDLDLB48WLOOeccCgsL8Xg89OzZk5NPPpn777+/08q0o/352R4J1q5d2+Zzsdvt9O7dm29961ssWLCgs4vXoZYviizLYvr06R1uc9xxx2FZFkOHDj3IpRMRETnwHJ1dABGRru7ZZ59t8/6ZZ55hxowZ7ZYPGjRot8f6zW9+wznnnMNZZ521P4vYzqeffsrkyZPp3bs31157Ld26dWPDhg189tln3Hfffdx4440HvUwd2ZvP9q9//SuJROJgFq/LuvDCC5k2bRrxeJyvvvqKhx56iP/+97989tlnjBw5srOL1yGPx8Pzzz/PJZdc0mb52rVr+fTTT/F4PJ1UMhERkQNLoVtEZDd2DAmfffYZM2bMaLe8K/n1r39Neno6s2fPJiMjo826ioqKzilUBw7Fz7YrGD16dJvP6LjjjuOMM87goYce4pFHHunEku3ctGnTeO2116isrCQnJ6d1+fPPP09+fj4lJSXU1NR0Ygn3TWNjIykpKZ1dDBER6cLUvFxEZD9obGzkxz/+Mb169cLtdjNgwAB+//vfY4xp3cayLBobG3n66adbm9teccUVAKxbt47rr7+eAQMG4PV6yc7O5txzz2Xt2rX7VJ5Vq1YxZMiQdoEbIC8vb4/KBLBp0yauuuoq8vPzcbvdDBkyhCeeeKLN8VqaD//tb3/jZz/7Gd26dSMlJYUzzjiDDRs27FP5O7Jjn+6Wpta///3v+ctf/kK/fv3w+XxMmTKFDRs2YIzhjjvuoKCgAK/Xy5lnnkl1dXW74/73v/9lwoQJpKSkkJaWxmmnncaSJUt2WZY5c+ZgWRZPP/10u3VvvfUWlmXxn//8B4D6+npuuukm+vTpg9vtJi8vj5NPPpl58+Z9vQ9kOyeccAIAa9asaV32+eefc+qpp5Keno7P52PixIl88sknbfb7OvddTU0NRx11FAUFBSxfvny325955pm43W5eeumlNsuff/55zjvvPOx2e4f7TZ8+nTFjxuD1esnKyuKCCy5od19NmjSJoUOHsmjRIiZOnIjP56O4uJh//OMfAHzwwQccffTReL1eBgwYwDvvvNPuPPPnz2fq1Kn4/X5SU1M58cQT+eyzz9ps09L3+oMPPuD6668nLy+PgoICZs6ciWVZvPrqq+2O+/zzz2NZFrNmzdrtZxQMBvnOd75DdnY2fr+fyy67rM0XEZdffjk5OTlEo9F2+06ZMoUBAwbs8vgfffQR5557Lr1798btdtOrVy9+9KMfEQqF2m27bNkyzjvvPHJzc1s/t5///Oe7vYYW++vn88EHH2TIkCG43W569OjBDTfcQG1tbbvtHn30UYqKivB6vRx11FF89NFHHZYrHA5z2223UVxc3PoZ/PSnPyUcDu/xtYmI7DUjIiJ75YYbbjDb//pMJBLmhBNOMJZlmWuuucY88MAD5vTTTzeAuemmm1q3e/bZZ43b7TYTJkwwzz77rHn22WfNp59+aowx5qWXXjIjRowwv/jFL8yjjz5qfvazn5nMzExTWFhoGhsbW48xc+ZMA5iZM2fusoxTpkwxaWlpZvHixbvcbldl2rJliykoKDC9evUyv/rVr8xDDz1kzjjjDAOYP/7xj+3KNGzYMDN8+HBz7733mv/5n/8xHo/H9O/f3wSDwT39aNt9ttu7/PLLTWFhYev7NWvWGMCMHDnSDB482Nx7773mf//3f43L5TLf+MY3zM9+9jNz7LHHmj//+c/mBz/4gbEsy1x55ZVtjvnMM88Yy7LMqaeeau6//35z1113mT59+piMjAyzZs2aXZa1X79+Ztq0ae2WX3nllSYzM9NEIhFjjDEXXXSRcblc5uabbzaPPfaYueuuu8zpp59upk+fvsefy47XfM8997RZvnDhQgOYCy64wBhjzLvvvmtcLpc55phjzB/+8Afzxz/+0QwfPty4XC7z+eeft+63p/fdk08+aQAze/ZsY4wxW7duNSNHjjS9e/c2K1eu3GWZW+6Pl156yVx00UVmwoQJresWLFhgADNr1iwzceJEM2TIkDb73nnnncayLHP++eebBx980Nx+++0mJyfH9OnTx9TU1LRuN3HiRNOjRw/Tq1cvc8stt5j777/fDB482NjtdvPiiy+abt26mV/+8pfmT3/6k+nZs6dJT083gUCgdf8vv/zSpKSkmO7du5s77rjD/O53vzN9+/Y1brfbfPbZZ+0+h8GDB5uJEyea+++/3/zud78ziUTC9OrVy3z7299ud/3Tpk0zRUVFu/yMWo47bNgwM2HCBPPnP//Z3HDDDcZms5njjz/eJBIJY4wxM2bMMID597//3Wb/srIyY7fbza9+9atdnufGG28006ZNM7/5zW/MI488Yq6++mpjt9vNOeec02a7hQsXGr/fb7Kzs82tt95qHnnkEfPTn/7UDBs2bJfH397++Pm87bbbDGBOOukkc//995vvf//7xm63m3HjxrX+fBljzGOPPWaA1uPddNNNJiMjw/Tr189MnDixdbt4PG6mTJlifD6fuemmm8wjjzxivv/97xuHw2HOPPPMPb42EZG9pdAtIrKXdgyG//znPw1g7rzzzjbbnXPOOcayrDahJCUlxVx++eXtjtlRMJ01a5YBzDPPPNO6bE9D99tvv23sdrux2+3mmGOOMT/96U/NW2+91eYP1d2V6eqrrzbdu3c3lZWVbZZfcMEFJj09vbXMLWXq2bNnmyDz97//3QDmvvvu22VZt7cvoTs3N9fU1ta2Lr/11lsNYEaMGGGi0Wjr8gsvvNC4XC7T1NRkjDGmvr7eZGRkmGuvvbbNebZs2WLS09PbLd/RrbfeapxOp6murm5dFg6HTUZGhrnqqqtal6Wnp5sbbrhh9xe/B1qu+fbbbzdbt241W7ZsMe+//74ZNWqUAczLL79sEomEKSkpMaecckprWDMmeY/17dvXnHzyyW2W7aij+2770F1WVmaGDBli+vXrZ9auXbvbMm8fuv/zn/8Yy7LM+vXrjTHG3HLLLaZfv37GGNMudK9du9bY7Xbz61//us3xFi9ebBwOR5vlEydONIB5/vnnW5ctW7bMAMZms7UJzm+99ZYBzJNPPtm67KyzzjIul8usWrWqddnmzZtNWlqaOf7449t9DuPHjzexWKxNuW699Vbjdrvb3IsVFRXG4XCY2267bZefUctxx4wZ0+Zn9O677zaA+de//mWMSYbGgoICc/7557fZ/9577zWWZZnVq1fv8jwd/Xv/9re/NZZlmXXr1rUuO/74401aWlqbZcaYNvfT7nzdn8+KigrjcrnMlClTTDweb93ugQceMIB54oknjDHGRCIRk5eXZ0aOHGnC4XDrdo8++qgB2oTuZ5991thsNvPRRx+1KevDDz9sAPPJJ5/s8fWJiOwNNS8XEfma3njjDex2Oz/4wQ/aLP/xj3+MMYb//ve/uz2G1+ttfR2NRqmqqqK4uJiMjIx9aoZ88sknM2vWLM444wwWLlzI3XffzSmnnELPnj157bXXdru/MYaXX36Z008/HWMMlZWVrY9TTjmFurq6duW67LLLSEtLa31/zjnn0L17d9544429Lv/eOPfcc0lPT299f/TRRwPJ/uIOh6PN8kgkwqZNmwCYMWMGtbW1XHjhhW2uz263c/TRRzNz5sxdnvf8888nGo3yyiuvtC57++23qa2t5fzzz29dlpGRweeff87mzZv3y/UC3HbbbeTm5tKtWzcmTZrEqlWruOuuuzj77LNZsGABpaWlXHTRRVRVVbVeV2NjIyeeeCIffvhh64B0e3vfbdy4kYkTJxKNRvnwww8pLCzcq3JPmTKFrKwsXnzxRYwxvPjii1x44YUdbvvKK6+QSCQ477zz2vz7dOvWjZKSknb/PqmpqVxwwQWt7wcMGEBGRgaDBg1qvSdg2/2xevVqAOLxOG+//TZnnXUW/fr1a92ue/fuXHTRRXz88ccEAoE257r22mvbNYe/7LLLCIfDrU3aAf72t78Ri8X2eIyC6667DqfT2fr+e9/7Hg6Ho/VnyGazcfHFF/Paa69RX1/fut1zzz3HscceS9++fXd5/O3/vRsbG6msrOTYY4/FGMP8+fMB2Lp1Kx9++CFXXXUVvXv3brO/ZVl7dB3b29efz3feeYdIJMJNN92Ezbbtz9Vrr70Wv9/P66+/DiS7elRUVPDd734Xl8vVut0VV1zR5rwAL730EoMGDWLgwIFt7qmW7hm7+5kXEdlXGkhNRORrWrduHT169GgTOGHbaObr1q3b7TFCoRC//e1vefLJJ9m0aVObvuB1dXX7VK5x48bxyiuvEIlEWLhwIa+++ip//OMfOeecc1iwYAGDBw/e6b5bt26ltraWRx99lEcffbTDbXYckK2kpKTNe8uyKC4u3ud+6Xtqx2DQ8od2r169Olze0ke2tLQU2NYfekd+v3+X5x0xYgQDBw7kb3/7G1dffTWQDFk5OTltjnn33Xdz+eWX06tXL8aMGcO0adO47LLL2gS8vXXddddx7rnnYrPZyMjIaO3zuv11XX755Tvdv66ujszMzL2+7y699FIcDgdfffUV3bp12+tyO51Ozj33XJ5//nmOOuooNmzYwEUXXdThtqWlpRhj2t1X2x9rewUFBe1CYXp6+m7vg61btxIMBjvsDz1o0CASiQQbNmxgyJAhrcs7CrcDBw5k3LhxPPfcc633w3PPPcc3vvENiouLO7yGHe14rampqXTv3r3Nz9Bll13GXXfdxauvvspll13G8uXLmTt3Lg8//PBuj79+/Xp+8Ytf8Nprr7UbtK7l37vly4j9NX3bvv58tvze3PHfxeVy0a9fv9b1Lc87fnZOp7Pdz1hpaSlfffUVubm5HZa1Kw0yKSKHF4VuEZEu4MYbb+TJJ5/kpptu4phjjiE9PR3Lsrjgggu+9jRZLpeLcePGMW7cOPr378+VV17JSy+9xG233bbTfVrOeckll+w0vA0fPvxrlWt/2dkAXDtb3hIsW67x2Wef7TBAbl8LtzPnn38+v/71r6msrCQtLY3XXnuNCy+8sM2+5513HhMmTODVV1/l7bff5p577uGuu+7ilVdeYerUqbs9R0dKSko46aSTOlzXcl333HPPTqcPS01NBfb+vjv77LN55plnuO+++/jtb3+7T2W/6KKLePjhh/nlL3/JiBEjdvrlTyKRwLIs/vvf/3b4b9lyDS329T7YF9vXGG/vsssu44c//CEbN24kHA7z2Wef8cADD+zzeToyePBgxowZw/Tp07nsssuYPn06LpeL8847b5f7xeNxTj75ZKqrq/l//+//MXDgQFJSUti0aRNXXHHFAZuO72D+u+xOIpFg2LBh3HvvvR2u3/GLABGR/UWhW0TkayosLOSdd96hvr6+TW33smXLWte32FnzzH/84x9cfvnl/OEPf2hd1tTU1OEovV/H2LFjASgrK9tlmXJzc0lLSyMej+803O2opYa1hTGGlStXdplwvqOioiIgOZr7nl7jjs4//3xuv/12Xn75ZfLz8wkEAm2aOLfo3r07119/Pddffz0VFRWMHj2aX//61/scunel5br8fv9ur2tv77sbb7yR4uJifvGLX5Cens7//M//7HX5xo8fT+/evXn//fe56667dnkdxhj69u1L//799/o8eyo3Nxefz9fhCOzLli3DZrPtcRi74IILuPnmm3nhhRcIhUI4nc42XQ12p7S0lMmTJ7e+b2hooKysjGnTprXZ7rLLLuPmm2+mrKyM559/ntNOO43MzMxdHnvx4sWsWLGCp59+mssuu6x1+YwZM9ps11I7/OWXX+5xuQ+Elt+by5cvb1NjHYlEWLNmTeu93bJdaWlpmxYm0WiUNWvWMGLEiNZlRUVFLFy4kBNPPHGfmsqLiOwr9ekWEfmapk2bRjweb1ej9cc//hHLstoEq5SUlA4Djd1ub1fDc//99xOPx/epTDNnzuywxqilb+j2TTY7KpPdbufb3/42L7/8cod/fG/durXdsmeeeaZNP9N//OMflJWVHZBguT+ccsop+P1+fvOb33Q4BVNH17ijQYMGMWzYMP72t7/xt7/9je7du3P88ce3ro/H4+2aaefl5dGjR482UxRVVlaybNkygsHg17iipDFjxlBUVMTvf/97Ghoa2q3f/rr25b77v//7P37yk59w66238tBDD+11+SzL4s9//jO33XYbl1566U63O/vss7Hb7dx+++3tymiMoaqqaq/P3RG73c6UKVP417/+1aYZd3l5Oc8//zzjx4/fbVeDFjk5OUydOpXp06fz3HPPceqpp7aZk3x3Hn300Tb34kMPPUQsFmv3M3ThhRdiWRY//OEPWb169R71GW+pWd7+szTGcN9997XZLjc3l+OPP54nnniC9evXt1l3IGuhd3TSSSfhcrn485//3Oa8jz/+OHV1dZx22mlA8ovE3NxcHn74YSKRSOt2Tz31VLvfa+eddx6bNm3ir3/9a7vzhUIhGhsbD8zFiMgRTzXdIiJf0+mnn87kyZP5+c9/ztq1axkxYgRvv/02//rXv7jppptaax4hGYjeeecd7r33Xnr06EHfvn05+uij+eY3v8mzzz5Leno6gwcPZtasWbzzzjtkZ2fvU5luvPFGgsEg3/rWtxg4cCCRSIRPP/2Uv/3tb/Tp04crr7xyt2X63e9+x8yZMzn66KO59tprGTx4MNXV1cybN4933nmn3Zy6WVlZjB8/niuvvJLy8nL+9Kc/UVxczLXXXrtvH+wB5vf7eeihh7j00ksZPXo0F1xwAbm5uaxfv57XX3+d4447bo+aBp9//vn84he/wOPxcPXVV7cZ9Km+vp6CggLOOeccRowYQWpqKu+88w6zZ89uU7v8wAMPcPvttzNz5kwmTZr0ta7LZrPx2GOPMXXqVIYMGcKVV15Jz5492bRpEzNnzsTv9/Pvf/8bYJ/vu3vuuYe6ujpuuOEG0tLS9nigsBZnnnkmZ5555i63KSoq4s477+TWW29l7dq1nHXWWaSlpbFmzRpeffVVrrvuOn7yk5/s1Xl35s4772TGjBmMHz+e66+/HofDwSOPPEI4HObuu+/eq2NddtllnHPOOQDccccde7VvJBLhxBNP5LzzzmP58uU8+OCDjB8/njPOOKPNdrm5uZx66qm89NJLZGRktAbQXRk4cCBFRUX85Cc/YdOmTfj9fl5++eV2fbsB/vznPzN+/HhGjx7NddddR9++fVm7di2vv/46CxYs2Ktr2le5ubnceuut3H777Zx66qmcccYZrZ/JuHHjWu85p9PJnXfeyXe+8x1OOOEEzj//fNasWcOTTz7Zrk/3pZdeyt///ne++93vMnPmTI477jji8TjLli3j73//O2+99VZrayARkf3qYA6VLiJyOOhoWqv6+nrzox/9yPTo0cM4nU5TUlJi7rnnnnZT7Cxbtswcf/zxxuv1GqB1qq6amhpz5ZVXmpycHJOammpOOeUUs2zZMlNYWNhmOq89nTLsv//9r7nqqqvMwIEDTWpqqnG5XKa4uNjceOONpry8fI/KZIwx5eXl5oYbbjC9evUyTqfTdOvWzZx44onm0UcfbVemF154wdx6660mLy/PeL1ec9ppp7Wbcmh39mXKsB3nrN5+iqrt7TjX9Pbbn3LKKSY9Pd14PB5TVFRkrrjiCjNnzpw9KnNpaakBDGA+/vjjNuvC4bC55ZZbzIgRI0xaWppJSUkxI0aMMA8++GCb7VrmI97dv+vOrrkj8+fPN2effbbJzs42brfbFBYWmvPOO8+8++67rdvs6X3X0WcXj8fNhRdeaBwOh/nnP/+503Ls7N9jRx3N022MMS+//LIZP368SUlJMSkpKWbgwIHmhhtuMMuXL9/tvoWFhea0005rtxxoN43bvHnzzCmnnGJSU1ONz+czkydPbp2zvsXO7qHthcNhk5mZadLT000oFNrlNe943A8++MBcd911JjMz06SmppqLL77YVFVVdbhPy5R811133R6dwxhjli5dak466SSTmppqcnJyzLXXXts6x/v2U6gZk5y7/Fvf+pbJyMgwHo/HDBgwwPzf//3fHp9rf/18PvDAA2bgwIHG6XSa/Px8873vfa/NHO0tHnzwwda51ceOHWs+/PBDM3HixDZThhmTnGLsrrvuMkOGDDFut9tkZmaaMWPGmNtvv93U1dXt8fWJiOwNy5iD2FZIREQOO++//z6TJ0/mpZdeaq3hEzlSxWIxevTowemnn87jjz9+wM7zr3/9i7POOosPP/yQCRMmHLDziIjI16c+3SIiIiL7yT//+U+2bt3aZrCyA+Gvf/0r/fr1Y/z48Qf0PCIi8vWpT7eIiIjI1/T555+zaNEi7rjjDkaNGsXEiRMPyHlefPFFFi1axOuvv85999130Efhjsfjux1kMDU1td2UbiIiRzKFbhEREZGv6aGHHmL69OmMHDmSp5566oCd58ILLyQ1NZWrr76a66+//oCdZ2c2bNhA3759d7nNbbfdxi9/+cuDUyARkUOA+nSLiIiIyB5pamri448/3uU2/fr1azdyuIjIkUyhW0REREREROQA0UBqIiIiIiIiIgfIEdenO5FIsHnzZtLS0g764CMiIiIiIiJyeDDGUF9fT48ePbDZdl6ffcSF7s2bN9OrV6/OLoaIiIiIiIgcBjZs2EBBQcFO1x9xoTstLQ1IfjB+v/+gnz8ajfL2228zZcoUnE7nQT+/yM7o3pSuSvemdFW6N6Wr0r0pXdXhdm8GAgF69erVmjF3plND94cffsg999zD3LlzKSsr49VXX+Wss87a5T7PPfccd999N6WlpaSnpzN16lTuuecesrOz9+icLU3K/X5/p4Vun8+H3+8/LG40OXzo3pSuSvemdFW6N6Wr0r0pXdXhem/urttypw6k1tjYyIgRI/jLX/6yR9t/8sknXHbZZVx99dUsWbKEl156iS+++IJrr732AJdUREREREREZO91ak331KlTmTp16h5vP2vWLPr06cMPfvADAPr27ct3vvMd7rrrrgNVRBEREREREZF9dkj16T7mmGP42c9+xhtvvMHUqVOpqKjgH//4B9OmTdvpPuFwmHA43Po+EAgAyaYN0Wj0gJd5Ry3n7Ixzi+yK7k3pqnRvSlele1O6Kt2b0lUdbvfmnl6HZYwxB7gse8SyrD3q0/3SSy9x1VVX0dTURCwW4/TTT+fll1/eaZ+AX/7yl9x+++3tlj///PP4fL79UXQRERERERE5wgSDQS666CLq6up2OV7YIRW6ly5dykknncSPfvQjTjnlFMrKyrjlllsYN24cjz/+eIf7dFTT3atXLyorKzttILUZM2Zw8sknH1aDB8ihT/emdFW6N6Wr0r0pXZXuTemqDrd7MxAIkJOTs9vQfUg1L//tb3/Lcccdxy233ALA8OHDSUlJYcKECdx5551079693T5utxu3291uudPp7NR/6M4+v8jO6N6Urkr3pnRVujelq9K9KV3V4XJv7uk1dOro5XsrGAxis7Utst1uB6CLVNiLiIiIiIiItOrU0N3Q0MCCBQtYsGABAGvWrGHBggWsX78egFtvvZXLLrusdfvTTz+dV155hYceeojVq1fzySef8IMf/ICjjjqKHj16dMYliIiIiIiIiOxUpzYvnzNnDpMnT259f/PNNwNw+eWX89RTT1FWVtYawAGuuOIK6uvreeCBB/jxj39MRkYGJ5xwgqYMExERERERkS6pU0P3pEmTdtks/Kmnnmq37MYbb+TGG288gKUSERERERER2T8OqT7dIiIiIiIiIocShW4RERERERGRA0ShW0REREREROQAUegWEREREREROUAUukVEREREREQOEIVuERERERERkQNEobsLCkViRGIJqhrCRGIJgpFYZxdJRERERERE9kGnztMt7YWjcR7+YDX/XLARj8NBUyzGWSMLuH5SEW6nvbOLJyIiIiIiIntBobsLCUVi/H3ORsbke7nhxuNoqqnDk5nOrBXlvDh7A+eOLcDn0j+ZiIiIiIjIoUIJrgux22ycPTSX4FNPsOaa6SQCAWx+PwMvuYTRV1yFw6beACIiIiIiIocShe4uxIRCBJ96guoHH2xdlggEWt+7rrwK0lI6q3giIiIiIiKyl1R12oU4PS5qp0/vcF3t9Ok4Pa6DXCIRERERERH5OhS6u5BEIEAiENjpunig/iCXSERERERERL4Ohe4uxO73Y/P7O1xn8/shJYV3vyo/yKUSERERERGRfaXQ3YWYWIysSy/tcF3W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VB8hHIx1eKxwMEZTY5RRU3rj9m4L2p5UzW0tcqTY4zYqI0aM4K9//SuPPPIIixYtYt26dYRCIXJychg5ciQ5OTkHspwiIiIiIgfF9nOd5/ZK2+l2JmFoCkZxeRy4fY4Og7fb58DndzF6SuGBLLKIdGF73THEZrMxcuRIRo4ceQCKIyIiIiJyaLBsybnOo+E4wycXMHu7Pt0thk8uIBE32NUdW+SIpR9/EREREZGvwem2M/rUZE32oj0YvVxEjiwK3SIiIiIiX5PDaWfUlELGTO3TZp5uBW4RUegWEREREdkPnO5kwPamuQDUpFxEANB8BCIiIiIiIiIHyD6H7pUrV/LWW28RCoUAMMbst0KJiIiIiIiIHA72OnRXVVVx0kkn0b9/f6ZNm0ZZWRkAV199NT/+8Y/3ewFFREREREREDlV7Hbp/9KMf4XA4WL9+PT6fr3X5+eefz5tvvrlfCyciIiIiIiJyKNvr4R3efvtt3nrrLQoKCtosLykpYd26dfutYCIiIiIiIiKHur2u6W5sbGxTw92iuroat9u9XwolIiIiIiIicjjY69A9YcIEnnnmmdb3lmWRSCS4++67mTx58n4tnIiIiIiIiMihbK+bl999992ceOKJzJkzh0gkwk9/+lOWLFlCdXU1n3zyyYEoo4iIiIiIiMghaa9ruocOHcqKFSsYP348Z555Jo2NjZx99tnMnz+foqKiA1FGERERERERkUPSXtd0A6Snp/Pzn/98f5dFRERERERE5LCyT6G7qamJRYsWUVFRQSKRaLPujDPO2C8FExERERERETnU7XXofvPNN7nsssuorKxst86yLOLx+H4pmIiIiIiIiMihbq/7dN94442ce+65lJWVkUgk2jwUuEVERERERES22evQXV5ezs0330x+fv6BKI+IiIiIiIjIYWOvQ/c555zD+++/fwCKIiIiIiIiInJ42es+3Q888ADnnnsuH330EcOGDcP5/9m787CoqsYP4N8Z1oEBERQBRQFRQATEJRPrdU3QVNRcMhdcXtyXMsutAuzVXg3LpdxTtLfXyhIzNTcSQzQVFNwQkCAMMcUFHHaY8/vDH/dlYIDBQNS+n+eZR+bec892z73Ouefecw0MNNbPmTOnzjJHRERERERE9Cyrdad7165dOHLkCIyNjREZGQmZTCatk8lk7HQTERERERER/b9ad7qXLFmCkJAQLFy4EHJ5re9OJyIiIiIiIvrbqHWvuaioCKNGjWKHm4iIiIiIiKgGte45BwQE4JtvvqmPvBARERERERE9V2p9e3lpaSlWrlyJw4cPw9PTs9JEap988kmdZY6IiIiIiIjoWVbrTvelS5fg7e0NALh8+bLGuvKTqhERERERERH93dW60338+PH6yAcRERERERHRc4ezoRERERERERHVE51GuocNG4awsDCYm5tj2LBh1Ybds2dPnWSMiIiIiIiI6FmnU6e7UaNG0vPajRo1qtcMERERERERET0vdOp0b9++HUuXLsX8+fOxffv2+s4TERERERER0XNB52e6Q0JCoFKp6jMvRERERERERM8VnTvdQoj6zAcRERERERHRc6dWs5fzPdxEREREREREuqvVe7rbtm1bY8f73r17fylDRERERERERM+LWnW6Q0JCOHs5ERERERERkY5q1el+/fXXYW1tXV95ISIiIiIiInqu6PxMN5/nJiIiIiIiIqodzl5OREREREREVE90vr1crVbXZz6IiIiIiIiInju1emUYEREREREREemOnW4iIiIiIiKiesJONxEREREREVE9YaebiIiIiIiIqJ7U6j3dZRITE7Fu3TokJCQAANzc3DB79my4uLjUaeaIiIiIiIiInmW1Hun+/vvv0b59e8TGxsLLywteXl44f/482rdvj++//74+8khERERERET0TKr1SPe7776LRYsWYenSpRrLg4KC8O677+K1116rs8wRERERERERPctqPdKdmZmJ8ePHV1o+duxYZGZm1kmmiIiIiIiIiJ4Hte509+zZE1FRUZWWnzx5Ei+//HKdZIqIiIiIiIjoeVDr28sHDx6MBQsWIDY2Fi+++CIA4Ndff8Xu3bsREhKCffv2aYQlIiIiIiIi+ruqdad7xowZAID169dj/fr1WtcBgEwmQ2lp6V/MHhEREREREdGzq9adbrVaXR/5ICIiIiIiInru1PqZ7vIKCgrqKh9EREREREREz51ad7pLS0vx4Ycfonnz5lAqlfjtt98AAO+//z6++OKLOs8gERERERER0bOq1p3uZcuWISwsDCtXroShoaG0vH379ti6dWudZo6IiIiIiIjoWVbrTvfOnTuxefNmjBkzBnp6etJyLy8vXLt2rU4zR0RERERERPQsq3WnOyMjA87OzpWWq9VqFBcX10mmiIiIiIiIiJ4Hte50t2vXDlFRUZWWf/fdd/D29q6TTBERERERERE9D2r9yrAPPvgAAQEByMjIgFqtxp49e5CYmIidO3di//799ZFHIiIiIiIiomdSrUe6/f398eOPP+LYsWMwNTXFBx98gISEBPz444945ZVX6iOPRERERERERM+kWo90A8DLL7+Mo0eP1nVeiIiIiIiIiJ4rtR7pdnJywt27dystf/DgAZycnOokU0RERERERETPg1p3utPS0lBaWlppeWFhITIyMuokU0RERERERETPA51vL9+3b5/09+HDh9GoUSPpe2lpKSIiIuDg4FCrxH/55Rd8/PHHiI2NRWZmJsLDwzFkyJAqw0dGRqJXr16VlmdmZsLGxqZWaRMRERERERHVN5073WWdYZlMhoCAAI11BgYGcHBwwKpVq2qVeG5uLry8vDBp0iQMGzZM5+0SExNhbm4ufbe2tq5VukRERERERERPgs6dbrVaDQBwdHTEuXPn0KRJk7+ceP/+/dG/f/9ab2dtbQ0LC4u/nD4RERERERFRfar17OWpqan1kY9a6dChAwoLC9G+fXsEBweje/fuVYYtLCxEYWGh9D0nJwcAUFxcjOLi4nrPa0VlaTZE2kTVYdukpxXbJj2t2DbpacW2SU+r561t6loOmRBC6BLw9OnTuHv3LgYOHCgt27lzJ4KCgpCbm4shQ4Zg3bp1MDIyeqwMy2SyGp/pTkxMRGRkJDp37ozCwkJs3boVX375Jc6cOYOOHTtq3SY4OBghISGVlv/3v/+FiYnJY+WViIiIiIiI/t7y8vLwxhtvIDs7W+Px54p07nT3798fPXv2xIIFCwAAly5dQseOHTFhwgS4ubnh448/xtSpUxEcHPxYGdal061Njx490LJlS3z55Zda12sb6ba3t0dWVla1FVNfiouLcfToUbzyyiswMDB44ukTVYVtk55WbJv0tGLbpKcV2yY9rZ63tpmTk4MmTZrU2OnW+fbyuLg4fPjhh9L3r7/+Gl27dsWWLVsAAPb29ggKCnrsTvfjeuGFF3Dy5Mkq1xsZGWkdfTcwMGjQHd3Q6RNVhW2TnlZsm/S0YtukpxXbJj2tnpe2qWsZdH5P9/3799GsWTPp+4kTJzQmQevSpQtu3LhRiyzWjbi4ONja2j7xdImIiIiIiIhqovNId7NmzZCamgp7e3sUFRXh/PnzGs9KP3z4sNZXK1QqFa5fvy59T01NRVxcHCwtLdGyZUssWrQIGRkZ2LlzJwBg9erVcHR0hLu7OwoKCrB161b8/PPPOHLkSK3SJSIiIiIiInoSdO50DxgwAAsXLsSKFSuwd+9emJiY4OWXX5bWX7x4Ea1bt65V4jExMejVq5f0fd68eQCAgIAAhIWFITMzE+np6dL6oqIivP3228jIyICJiQk8PT1x7NgxjTiIiIiIiIiInhY6d7o//PBDDBs2DD169IBSqcSOHTtgaGgord+2bRv69etXq8R79uyJ6uZxCwsL0/j+7rvv4t13361VGkREREREREQNRedOd5MmTfDLL78gOzsbSqUSenp6Gut3794NpVJZ5xkkIiIiIiIielbp3Oku06hRI63LLS0t/3JmiIiIiIiIiJ4nOs9eTkRERERERES1w043ERERERERUT1hp5uIiIiIiIionrDTTURERERERFRPdJpIbd++fTpHOHjw4MfODBEREREREdHzRKdO95AhQ3SKTCaTobS09K/kh4iIiIiIiOi5oVOnW61W13c+iIiIiIiIiJ47fKabiIiIiIiIqJ7oNNJdUW5uLk6cOIH09HQUFRVprJszZ06dZIyIiIiIiIjoWVfrTveFCxcwYMAA5OXlITc3F5aWlsjKyoKJiQmsra3Z6SYiIiIiIiL6f7W+vfytt97CoEGDcP/+fSgUCvz666/4/fff0alTJ4SGhtZHHomIiIiIiIieSbXudMfFxeHtt9+GXC6Hnp4eCgsLYW9vj5UrV2Lx4sX1kUciIiIiIiKiZ1KtO90GBgaQyx9tZm1tjfT0dABAo0aNcOPGjbrNHREREREREdEzrNbPdHt7e+PcuXNo06YNevTogQ8++ABZWVn48ssv0b59+/rIIxEREREREdEzqdYj3cuXL4etrS0AYNmyZWjcuDGmT5+OO3fuYNOmTXWeQSIiIiIiIqJnVa1Hujt37iz9bW1tjUOHDtVphoiIiIiIiIieF7Ue6e7duzcePHhQaXlOTg569+5dF3kiIiIiIiIiei7UutMdGRmJoqKiSssLCgoQFRVVJ5kiIiIiIiIieh7ofHv5xYsXpb+vXr2KW7duSd9LS0tx6NAhNG/evG5zR0RERERERPQM07nT3aFDB8hkMshkMq23kSsUCqxbt65OM0dERERERET0LNO5052amgohBJycnHD27Fk0bdpUWmdoaAhra2vo6enVSyaJiIiIiIiInkU6d7pbtWoFAFCr1fWWGSIiIiIiIqLnSa1fGQYAKSkpWL16NRISEgAA7dq1w9y5c9G6des6zRwRERERERHRs6zWs5cfPnwY7dq1w9mzZ+Hp6QlPT0+cOXMG7u7uOHr0aH3kkYiIiIiIiOiZVOuR7oULF+Ktt97Cv//970rLFyxYgFdeeaXOMkdERERERET0LKv1SHdCQgImT55cafmkSZNw9erVOskUERERERER0fOg1p3upk2bIi4urtLyuLg4WFtb10WeiIiIiIiIiJ4LOt9evnTpUsyfPx+BgYGYMmUKfvvtN/j4+AAAoqOjsWLFCsybN6/eMkpERERERET0rNG50x0SEoJp06bh/fffh5mZGVatWoVFixYBAOzs7BAcHIw5c+bUW0aJiIiIiIiInjU6d7qFEAAAmUyGt956C2+99RYePnwIADAzM6uf3BERERERERE9w2o1e7lMJtP4zs42ERERERERUdVq1elu27ZtpY53Rffu3ftLGSIiIiIiIiJ6XtSq0x0SEoJGjRrVV16IiIiIiIiIniu16nS//vrrfC0YERERERERkY50fk93TbeVExEREREREZEmnTvdZbOXExEREREREZFudL69XK1W12c+iIiIiIiIiJ47Oo90ExEREREREVHtsNNNREREREREVE/Y6SYiIiIiIiKqJ+x0ExEREREREdUTdrqJiIiIiIiI6gk73URERERERET1hJ1uIiIiIiIionrCTjcRERERERFRPWGnm4iIiIiIiKiesNNNREREREREVE/Y6SYiIiIiIiKqJ+x0ExEREREREdUTdrqJiIiIiIiI6gk73URERERERET1hJ1uIiIiIiIionrCTjcRERERERFRPWGnm4iIiIiIiKiesNNNREREREREVE/Y6SYiIiIiIiKqJ+x0ExEREREREdUTdrqJiIiIiIiI6gk73URERERERET1hJ1uIiIiIiIionrCTjcRERERERFRPWGnm4iIiIiIiKiesNNNREREREREVE/0GzoDT6vS0lIUFxfXebzFxcXQ19dHQUEBSktL6zx+osfFtklPK7ZNelrp2jYNDQ0hl3Ocg4jo74qd7gqEELh16xYePHhQb/Hb2Njgxo0bkMlk9ZIG0eNg26SnFdsmPa10bZtyuRyOjo4w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bSokJETrUU4Pvh58rjIREREREdGTgI8Moza1YcMGrbt6P6hz585tnI1uxMfH6zsFIiIiIiJqJ9h0U5tycHDQdwpERERERERthqeXExEREREREekIm24iIiIiIiIiHWHTTURERERERKQjbLqJiIiIiIiIdIRNNxEREREREZGOsOkmIiIiIiKidqG6sgK1NdUoKy5CbU01qisr9J3Sn8am+wkRGRkJmUxW73Xp0iVkZGRg/PjxsLGxgbGxMbp3746wsDAUFBQAAK5cuaK1jrm5Ofr27Ys5c+YgOztbazvx8fFSnIGBARwdHREVFaU117Rp0+Di4gITExP07NkTixcvRlVVVZt/JkRERERE9PioqapC6u4diH31Fen1854dqHnMewk+p1tHqisrYCCXo/LePShNTaGprYWR0lin2wwODkZcXJzWMplMhqFDh2Ls2LE4dOgQrKyscOXKFezZswf37t3Tiv3+++/Rt29flJWV4fz58/j000/h5eWFvXv3IiAgQIqzsLBAVlYWNBoNMjIyEBUVhRs3buDQoUP49ddfodFo8MUXX8DV1RWZmZmYMWMG7t27h1WrVul0/4mIiIiI6PFUXVmB1N078NOOBGlZ5b17SNl+//3g8S/ovJ/SFTbdOlD3C83Zg3ukpntgyHgMmRAKA0PdfeRKpRJ2dnZay3bt2oXi4mJs2LABhv+3bRcXF/j7+9dbv0uXLtL6PXr0wLhx4xAQEIBp06bh8uXLkMvlAO438nVx9vb2mDdvHj744AOUl5cjODgYwcHB0pw9evRAVlYWYmNj2XQTEREREVGDDORynD24p8GxMwf2wPe5l9o4o9bD08ubIYRAdUVFi1+V5WU4tWsbftqRgMr/O5Jc9wtN6u5t9+MqWzaXEOJP529nZ4eamhrs3LnzkeczMDDA/PnzcfXqVaSlpTUaZ2JiAo1Gg5qamgbHi4uL0blz50faNhERERERdRyV9+5J/VODY2VlbZxR6+GR7mbUVFbisykvtijWxNwCMz7/qslfaAaPewHb3n8T5XdLmp1v3qbtMDJu+SkU+/btg5mZmfQ+JCQE27Ztw8KFC/Hyyy9j5syZGDJkCJ599llMnjwZtra2zc7p4eEB4P612kOGDKk3np2djXXr1sHHxwfm5ub1xi9duoQ1a9bwKDcRERERETVKaWoKpalpg4230tQUSpVKD1m1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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import seaborn as sns\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "# Make sure the data is sorted by peak_memory for proper line plotting\n",
+ "df_sorted = combined_df.sort_values(by=\"peak_memory\")\n",
+ "\n",
+ "plt.figure(figsize=(10, 6))\n",
+ "sns.lineplot(\n",
+ " data=df_sorted,\n",
+ " x=\"peak_memory\",\n",
+ " y=\"total_step_time\",\n",
+ " hue=\"lines\", # One line per ac_mode\n",
+ " marker=\"o\" # Add markers for clarity\n",
+ ")\n",
+ "plt.title(\"Total Step Time vs. Peak Memory by ac_mode\")\n",
+ "plt.xlabel(\"Peak Memory (MB)\") # Adjust label if needed\n",
+ "plt.ylabel(\"Total Step Time (s)\") # Adjust label if needed\n",
+ "plt.grid(True)\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAA90AAAJOCAYAAACqS2TfAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQABAABJREFUeJzs3Xd8VfX9x/HXOXffJDebDLIhEPYWVBBwgGDdioqCiltra23tr9rWUUertlr33ohaVKxb0TIVEGTvECAJkL1ukpvc+f39ccOFkDAlJIHP8/G4j3DPuPdz7rkJ932/42hKKYUQQgghhBBCCCGOOr29CxBCCCGEEEIIIY5XErqFEEIIIYQQQog2IqFbCCGEEEIIIYRoIxK6hRBCCCGEEEKINiKhWwghhBBCCCGEaCMSuoUQQgghhBBCiDYioVsIIYQQQgghhGgjErqFEEIIIYQQQog2IqFbCCGEEEIIIYRoIxK6hRCiE5k7dy6apjF37tz2LuWYu+aaa8jIyGjvMk5Ib775JpqmsWzZsvYu5bgkr2/bGDNmDGPGjGnvMoQQQkK3EEIcjKZph3Q7lCD8yCOP8Mknn7R5zQBr1qzhkksuIT09HavVSteuXTnrrLN45pln2q2mfR3N1/ZEsH379mavi8FgIC0tjQsvvJCVK1e2d3mt2v1FkaZpTJ8+vdVtTj31VDRNo2/fvse4OiGEEKLtGdu7ACGE6OjeeeedZvfffvttZs+e3WJ5r169DvpYjzzyCJdccgkXXHDB0SyxhR9//JGxY8eSlpbGDTfcQGJiIoWFhSxevJinnnqK22+//ZjX1JrDeW1feeUVAoHAsSyvw7riiiuYOHEifr+fDRs28MILL/DVV1+xePFiBg4c2N7ltcpqtTJjxgyuuuqqZsu3b9/Ojz/+iNVqbafKhBBCiLYloVsIIQ5i35CwePFiZs+e3WJ5R/Lwww8TGRnJ0qVLiYqKarautLS0fYpqRWd8bTuCwYMHN3uNTj31VM477zxeeOEFXnrppXasbP8mTpzIp59+Snl5OXFxcaHlM2bMICEhgezsbKqqqtqxwiNTX19PWFhYe5chhBCiA5Pu5UIIcRTU19fz+9//ntTUVCwWCz179uSf//wnSqnQNpqmUV9fz1tvvRXqbnvNNdcAkJ+fz6233krPnj2x2WzExsZy6aWXsn379iOqJy8vjz59+rQI3ABdunQ5pJoAdu7cybRp00hISMBisdCnTx9ef/31Zo+3u/vwBx98wD333ENiYiJhYWGcd955FBYWHlH9rdl3TPfurtb//Oc/ee6558jKysJutzNu3DgKCwtRSvHggw+SkpKCzWbj/PPPp7KyssXjfvXVV4waNYqwsDAiIiI455xzWLdu3QFrWbZsGZqm8dZbb7VY980336BpGp9//jkAtbW13HHHHWRkZGCxWOjSpQtnnXUWy5cv/2UvyF5OP/10ALZt2xZatmTJEs4++2wiIyOx2+2MHj2aH374odl+v+R9V1VVxUknnURKSgqbNm066Pbnn38+FouFmTNnNls+Y8YMJk2ahMFgaHW/6dOnM2TIEGw2GzExMVx++eUt3ldjxoyhb9++rF69mtGjR2O32+nevTsffvghAPPmzWP48OHYbDZ69uzJd9991+J5VqxYwYQJE3A4HISHh3PGGWewePHiZtvsHns9b948br31Vrp06UJKSgpz5sxB0zRmzZrV4nFnzJiBpmksWrTooK+Ry+XipptuIjY2FofDwdSpU5t9EXH11VcTFxeH1+ttse+4cePo2bPnAR9/wYIFXHrppaSlpWGxWEhNTeV3v/sdDQ0NLbbduHEjkyZNIj4+PvS6/fnPfz7oMex2tH4/n3/+efr06YPFYiE5OZnbbruN6urqFtu9/PLLdOvWDZvNxkknncSCBQtarcvtdnPffffRvXv30Gvwxz/+EbfbfcjHJoQQh00JIYQ4LLfddpva+89nIBBQp59+utI0TV1//fXq2WefVeeee64C1B133BHa7p133lEWi0WNGjVKvfPOO+qdd95RP/74o1JKqZkzZ6oBAwaoe++9V7388svqnnvuUdHR0So9PV3V19eHHmPOnDkKUHPmzDlgjePGjVMRERFqzZo1B9zuQDUVFxerlJQUlZqaqv72t7+pF154QZ133nkKUE8++WSLmvr166f69++vnnjiCfWnP/1JWa1W1aNHD+VyuQ71pW3x2u7t6quvVunp6aH727ZtU4AaOHCg6t27t3riiSfUX/7yF2U2m9WIESPUPffco0455RT19NNPq9/85jdK0zR17bXXNnvMt99+W2maps4++2z1zDPPqEcffVRlZGSoqKgotW3btgPWmpWVpSZOnNhi+bXXXquio6OVx+NRSik1efJkZTab1Z133qleffVV9eijj6pzzz1XTZ8+/ZBfl32P+fHHH2+2fNWqVQpQl19+uVJKqe+//16ZzWZ18sknq3/961/qySefVP3791dms1ktWbIktN+hvu/eeOMNBailS5cqpZQqKytTAwcOVGlpaWrLli0HrHn3+2PmzJlq8uTJatSoUaF1K1euVIBatGiRGj16tOrTp0+zfR966CGlaZq67LLL1PPPP68eeOABFRcXpzIyMlRVVVVou9GjR6vk5GSVmpqq7rrrLvXMM8+o3r17K4PBoN5//32VmJio7r//fvXvf/9bde3aVUVGRiqn0xnaf+3atSosLEwlJSWpBx98UP3jH/9QmZmZymKxqMWLF7d4HXr37q1Gjx6tnnnmGfWPf/xDBQIBlZqaqi6++OIWxz9x4kTVrVu3A75Gux+3X79+atSoUerpp59Wt912m9J1XZ122mkqEAgopZSaPXu2AtRnn33WbP+ioiJlMBjU3/72twM+z+23364mTpyoHnnkEfXSSy+p6667ThkMBnXJJZc0227VqlXK4XCo2NhYdffdd6uXXnpJ/fGPf1T9+vU74OPv7Wj8ft53330KUGeeeaZ65pln1K9//WtlMBjUsGHDQr9fSin16quvKiD0eHfccYeKiopSWVlZavTo0aHt/H6/GjdunLLb7eqOO+5QL730kvr1r3+tjEajOv/88w/52IQQ4nBJ6BZCiMO0bzD85JNPFKAeeuihZttdcsklStO0ZqEkLCxMXX311S0es7VgumjRIgWot99+O7TsUEP3t99+qwwGgzIYDOrkk09Wf/zjH9U333zT7IPqwWq67rrrVFJSkiovL2+2/PLLL1eRkZGhmnfX1LVr12ZB5j//+Y8C1FNPPXXAWvd2JKE7Pj5eVVdXh5bffffdClADBgxQXq83tPyKK65QZrNZNTY2KqWUqq2tVVFRUeqGG25o9jzFxcUqMjKyxfJ93X333cpkMqnKysrQMrfbraKiotS0adNCyyIjI9Vtt9128IM/BLuP+YEHHlBlZWWquLhYzZ07Vw0aNEgB6qOPPlKBQEBlZ2er8ePHh8KaUsH3WGZmpjrrrLOaLdtXa++7vUN3UVGR6tOnj8rKylLbt28/aM17h+7PP/9caZqmCgoKlFJK3XXXXSorK0sppVqE7u3btyuDwaAefvjhZo+3Zs0aZTQamy0fPXq0AtSMGTNCyzZu3KgApet6s+D8zTffKEC98cYboWUXXHCBMpvNKi8vL7Rs165dKiIiQp122mktXoeRI0cqn8/XrK67775bWSyWZu/F0tJSZTQa1X333XfA12j34w4ZMqTZ7+hjjz2mAPXf//5XKRUMjSkpKeqyyy5rtv8TTzyhNE1TW7duPeDztHa+//73vytN01R+fn5o2WmnnaYiIiKaLVNKNXs/Hcwv/f0sLS1VZrNZjRs3Tvn9/tB2zz77rALU66+/rpRSyuPxqC5duqiBAwcqt9sd2u7ll19WQLPQ/c477yhd19WCBQua1friiy8qQP3www+HfHxCCHE4pHu5EEL8Ql9++SUGg4Hf/OY3zZb//ve/RynFV199ddDHsNlsoX97vV4qKiro3r07UVFRR9QN+ayzzmLRokWcd955rFq1iscee4zx48fTtWtXPv3004Pur5Tio48+4txzz0UpRXl5eeg2fvx4ampqWtQ1depUIiIiQvcvueQSkpKS+PLLLw+7/sNx6aWXEhkZGbo/fPhwIDhe3Gg0Nlvu8XjYuXMnALNnz6a6uporrrii2fEZDAaGDx/OnDlzDvi8l112GV6vl48//ji07Ntvv6W6uprLLrsstCwqKoolS5awa9euo3K8APfddx/x8fEkJiYyZswY8vLyePTRR7noootYuXIlubm5TJ48mYqKitBx1dfXc8YZZzB//vzQhHSH+77bsWMHo0ePxuv1Mn/+fNLT0w+r7nHjxhETE8P777+PUor333+fK664otVtP/74YwKBAJMmTWp2fhITE8nOzm5xfsLDw7n88stD93v27ElUVBS9evUKvSdgz/tj69atAPj9fr799lsuuOACsrKyQtslJSUxefJkFi5ciNPpbPZcN9xwQ4vu8FOnTsXtdoe6tAN88MEH+Hy+Q56j4MYbb8RkMoXu33LLLRiNxtDvkK7rXHnllXz66afU1taGtnv33Xc55ZRTyMzMPODj732+6+vrKS8v55RTTkEpxYoVKwAoKytj/vz5TJs2jbS0tGb7a5p2SMextyP9/fzuu+/weDzccccd6Pqej6s33HADDoeDL774AggO9SgtLeXmm2/GbDaHtrvmmmuaPS/AzJkz6dWrFzk5Oc3eU7uHZxzsd14IIY6UTKQmhBC/UH5+PsnJyc0CJ+yZzTw/P/+gj9HQ0MDf//533njjDXbu3NlsLHhNTc0R1TVs2DA+/vhjPB4Pq1atYtasWTz55JNccsklrFy5kt69e+9337KyMqqrq3n55Zd5+eWXW91m3wnZsrOzm93XNI3u3bsf8bj0Q7VvMNj9QTs1NbXV5bvHyObm5gJ7xkPvy+FwHPB5BwwYQE5ODh988AHXXXcdEAxZcXFxzR7zscce4+qrryY1NZUhQ4YwceJEpk6d2izgHa4bb7yRSy+9FF3XiYqKCo153fu4rr766v3uX1NTQ3R09GG/76ZMmYLRaGTDhg0kJiYedt0mk4lLL72UGTNmcNJJJ1FYWMjkyZNb3TY3NxelVIv31d6PtbeUlJQWoTAyMvKg74OysjJcLler46F79epFIBCgsLCQPn36hJa3Fm5zcnIYNmwY7777buj98O677zJixAi6d+/e6jHsa99jDQ8PJykpqdnv0NSpU3n00UeZNWsWU6dOZdOmTfz888+8+OKLB338goIC7r33Xj799NMWk9btPt+7v4w4WpdvO9Lfz91/N/c9L2azmaysrND63T/3fe1MJlOL37Hc3Fw2bNhAfHx8q7V2pEkmhRDHFwndQgjRAdx+++288cYb3HHHHZx88slERkaiaRqXX375L75MltlsZtiwYQwbNowePXpw7bXXMnPmTO6777797rP7Oa+66qr9hrf+/fv/orqOlv1NwLW/5buD5e5jfOedd1oNkHu3wu3PZZddxsMPP0x5eTkRERF8+umnXHHFFc32nTRpEqNGjWLWrFl8++23PP744zz66KN8/PHHTJgw4aDP0Zrs7GzOPPPMVtftPq7HH398v5cPCw8PBw7/fXfRRRfx9ttv89RTT/H3v//9iGqfPHkyL774Ivfffz8DBgzY75c/gUAATdP46quvWj2Xu49htyN9HxyJvVuM9zZ16lR++9vfsmPHDtxuN4sXL+bZZ5894udpTe/evRkyZAjTp09n6tSpTJ8+HbPZzKRJkw64n9/v56yzzqKyspL/+7//Iycnh7CwMHbu3Mk111zTZpfjO5bn5WACgQD9+vXjiSeeaHX9vl8ECCHE0SKhWwghfqH09HS+++47amtrm7V2b9y4MbR+t/11z/zwww+5+uqr+de//hVa1tjY2Oosvb/E0KFDASgqKjpgTfHx8UREROD3+/cb7va1u4V1N6UUW7Zs6TDhfF/dunUDgrO5H+ox7uuyyy7jgQce4KOPPiIhIQGn09msi/NuSUlJ3Hrrrdx6662UlpYyePBgHn744SMO3Qey+7gcDsdBj+tw33e333473bt359577yUyMpI//elPh13fyJEjSUtLY+7cuTz66KMHPA6lFJmZmfTo0eOwn+dQxcfHY7fbW52BfePGjei6fshh7PLLL+fOO+/kvffeo6GhAZPJ1GyowcHk5uYyduzY0P26ujqKioqYOHFis+2mTp3KnXfeSVFRETNmzOCcc84hOjr6gI+9Zs0aNm/ezFtvvcXUqVNDy2fPnt1su92tw2vXrj3kutvC7r+bmzZtatZi7fF42LZtW+i9vXu73NzcZj1MvF4v27ZtY8CAAaFl3bp1Y9WqVZxxxhlH1FVeCCGOlIzpFkKIX2jixIn4/f4WLVpPPvkkmqY1C1ZhYWGtBhqDwdCiheeZZ57B7/cfUU1z5sxptcVo99jQvbtstlaTwWDg4osv5qOPPmr1w3dZWVmLZW+//XazcaYffvghRUVFbRIsj4bx48fjcDh45JFHWr0EU2vHuK9evXrRr18/PvjgAz744AOSkpI47bTTQuv9fn+LbtpdunQhOTm52SWKysvL2bhxIy6X6xccUdCQIUPo1q0b//znP6mrq2uxfu/jOpL33V//+lf+8Ic/cPfdd/PCCy8cdn2apvH0009z3333MWXKlP1ud9FFF2EwGHjggQda1KiUoqKi4rCfuzUGg4Fx48bx3//+t1k37pKSEmbMmMHIkSMPOtRgt7i4OCZMmMD06dN59913Ofvss5tdk/xgXn755WbvxRdeeAGfz9fid+iKK65A0zR++9vfsnXr1kMaM767ZXnv11IpxVNPPdVsu/j4eE477TRef/11CgoKmq1ry1bofZ155pmYzWaefvrpZs/72muvUVNTwznnnAMEv0iMj4/nxRdfxOPxhLZ78803W/xdmzRpEjt37uSVV15p8XwNDQ3U19e3zcEIIU540tIthBC/0LnnnsvYsWP585//zPbt2xkwYADffvst//3vf7njjjtCLY8QDETfffcdTzzxBMnJyWRmZjJ8+HB+9atf8c477xAZGUnv3r1ZtGgR3333HbGxsUdU0+23347L5eLCCy8kJycHj8fDjz/+yAcffEBGRgbXXnvtQWv6xz/+wZw5cxg+fDg33HADvXv3prKykuXLl/Pdd9+1uKZuTEwMI0eO5Nprr6Wk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EVFdV+lG96FDhzBmzBhkZmaWmieTyaBWq6skMCIiIiIiIqK6rtLPdE+fPh1Dhw5FRkYGNBqNzocNbiIiIiIiIqL/qXSj+88//8Ts2bPRqFGj6oiHiIiIiIiI6KlR6Ub3kCFDEBUVVQ2hEBERERERET1dKv1M98cff4yhQ4ciOjoa3t7eMDEx0Zk/Y8aMKguOiIiIiIiIqC6rdKN7x44dOHLkCMzNzREVFQWZTCbNk8lkbHQTERERERER/b9KN7oXLlyI8PBwzJ8/H3J5pe9OJyIiIiIiInpmVLrVXFhYiOHDh7PBTURERERERFSBSrecg4KC8M0331RHLERERERERERPlUrfXq5Wq7F8+XIcPnwYbdu2LTWQ2ocfflhlwRERERERERHVZZVudF+4cAG+vr4AgIsXL+rMKzmoGhEREREREdGzrtKN7uPHj1dHHERERERERERPHY6GRkRERERERFRNDOrpHjx4MCIiImBtbY3BgweXm3b37t1VEhgRERERERFRXWdQo7tevXrS89r16tWr1oCIiIiIiIiInhYGNbq3bt2KxYsXY+7cudi6dWt1x0RERERERET0VDD4me7w8HCoVKrqjIWIiIiIiIjoqWJwo1sIUZ1xEBERERERET11KjV6Od/DTURERERERGS4Sr2nu1WrVhU2vO/du/e3AiIiIiIiIiJ6WlSq0R0eHs7Ry4mIiIiIiIgMVKlG92uvvQZ7e/vqioWIiIiIiIjoqWLwM918npuIiIiIiIiocjh6OREREREREVE1Mfj2co1GU51xEBERERERET11KvXKMCIiIiIiIiIyHBvdRERERERERNWEjW4iIiIiIiKiasJGNxEREREREVE1qdR7urWSk5Oxbt06JCUlAQA8PT0xffp0uLu7V2lwRERERERERHVZpXu6d+3ahTZt2iA+Ph4+Pj7w8fHB2bNn0aZNG+zatas6YiQiIiIiIiKqkyrd0/32229jwYIFWLx4sc700NBQvP3223j11VerLDgiIiIiIiKiuqzSPd0ZGRkYM2ZMqemjRo1CRkZGlQRFRERERERE9DSodKO7R48eiI6OLjX95MmTePHFF6skKCIiIiIiIqKnQaVvLx8wYADmzZuH+Ph4PP/88wCAX3/9FTt37kR4eDj27dunk5aIiIiIiIjoWVXpRveUKVMAAJ9++ik+/fRTvfMAQCaTQa1W/83wiIiIiIiIiOquSje6NRpNdcRBRERERERE9NSp9DPdJeXn51dVHERERERERERPnUo3utVqNd5//300adIESqUS169fBwC89957+Pzzz6s8QCIiIiIiIqK6qtKN7iVLliAiIgLLly+HqampNL1NmzbYvHlzlQZHREREREREVJdVutG9fft2bNq0CSNHjoSRkZE03cfHB7/99luVBkdERERERERUl1W60Z2eng43N7dS0zUaDYqKiqokKCIiIiIiIqKnQaUb3a1bt0Z0dHSp6d999x18fX2rJCgiIiIiIiKip0GlXxm2aNEiBAUFIT09HRqNBrt370ZycjK2b9+O/fv3V0eMRERERERERHVSpXu6AwMD8cMPPyAyMhKWlpZYtGgRkpKS8MMPP+Cll16qjhiJiIiIiIiI6qRK93QDwIsvvoijR49WdSxERERERERET5VK93S7urri7t27pabfv38frq6uVRIUERERERER0dOg0o3uGzduQK1Wl5peUFCA9PT0KgmKiIiIiIiI6Glg8O3l+/btk/4+fPgw6tWrJ31Xq9U4duwYnJ2dK7Xyn3/+GStWrEB8fDwyMjKwZ88eDBw4sMz0UVFR6NmzZ6npGRkZcHBwqNS6iYiIiIiIiKqbwY1ubWNYJpMhKChIZ56JiQmcnZ2xatWqSq08NzcXPj4+GD9+PAYPHmzwcsnJybC2tpa+29vbV2q9RERERERERP8EgxvdGo0GAODi4oIzZ86gQYMGf3vlffr0QZ8+fSq9nL29PWxsbP72+omIiIiIiIiqU6VHL09NTa2OOCqlXbt2KCgoQJs2bRAWFoZu3bqVmbagoAAFBQXS95ycHABAUVERioqKqj3WJ6WNrTbH+KxjHdVurJ/ajfVT+7GOajfWT+3G+qn9WEe1W12pH0PjkwkhhCEJT506hbt376Jfv37StO3btyM0NBS5ubkYOHAg1q1bBzMzsycKWCaTVfhMd3JyMqKiotCxY0cUFBRg8+bN+OKLL3D69Gm0b99e7zJhYWEIDw8vNf2rr76ChYXFE8VKREREREREz7a8vDy8/vrryM7O1nn8+XEGN7r79OmDHj16YN68eQCACxcuoH379hg7diw8PT2xYsUKTJw4EWFhYU8UsCGNbn26d++OZs2a4YsvvtA7X19Pt5OTEzIzM8stmJpWVFSEo0eP4qWXXoKJiUlNh0N6sI5qN9ZP7cb6qf1YR7Ub66d2Y/3Ufqyj2q2u1E9OTg4aNGhQYaPb4NvLExIS8P7770vfv/76a3Tu3BmfffYZAMDJyQmhoaFP3Oh+Us899xxOnjxZ5nwzMzO9ve8mJia1ugK16kqczzLWUe3G+qndWD+1H+uodmP91G6sn9qPdVS71fb6MTQ2g9/TnZWVhUaNGknfT5w4oTMIWqdOnXDr1q1KhFg1EhIS4Ojo+I+vl4iIiIiIiKgiBvd0N2rUCKmpqXByckJhYSHOnj2r86z0gwcPKn0VQqVS4dq1a9L31NRUJCQkwNbWFs2aNcOCBQuQnp6O7du3AwBWr14NFxcXeHl5IT8/H5s3b8ZPP/2EI0eOVGq9RERERERERP8Egxvdffv2xfz587Fs2TLs3bsXFhYWePHFF6X558+fR4sWLSq18ri4OPTs2VP6Pnv2bABAUFAQIiIikJGRgbS0NGl+YWEh5syZg/T0dFhYWKBt27aIjIzUyYOIiIiIiIiotjC40f3+++9j8ODB6N69O5RKJbZt2wZTU1Np/pYtW/Dyyy9XauU9evRAeeO4RURE6Hx/++238fbbb1dqHUREREREREQ1xeBGd4MGDfDzzz8jOzsbSqUSRkZGOvN37twJpVJZ5QESERERERER1VUGN7q16tWrp3e6ra3t3w6GiIiIiIiI6Gli8OjlRERERERERFQ5bHQTERERERERVRM2uomIiIiIiIiqCRvdRERERERERNXEoIHU9u3bZ3CGAwYMeOJgiIiIiIiIiJ4mBjW6Bw4caFBmMpkMarX678RDRERERERE9NQwqNGt0WiqOw4iIiIiIiKipw6f6SYiIiIiIiKqJgb1dD8uNzcXJ06cQFpaGgoLC3XmzZgxo0oCIyIiIiIiIqrrKt3oPnfuHPr27Yu8vDzk5ubC1tYWmZmZsLCwgL29PRvdRERERERERP+v0reXz5o1C/3790dWVhYUCgV+/fVX3Lx5Ex06dMDKlSurI0YiIiIiIiKiOqnSje6EhATMmTMHcrkcRkZGKCgogJOTE5YvX4533nmnOmIkIiIiIiIiqpMq3eg2MTGBXP5oMXt7e6SlpQEA6tWrh1u3blVtdERERERERER1WKWf6fb19cWZM2fQsmVLdO/eHYsWLUJmZia++OILtGnTpjpiJCIiIiIiIqqTKt3TvXTpUjg6OgIAlixZgvr162Py5Mn466+/sHHjxioPkIiIiIiIiKiuqnRPd8eOHaW/7e3tcejQoSoNiIiIiIiIiOhpUeme7l69euH+/fulpufk5KBXr15VERMRERERERHRU6HSje6oqCgUFhaWmp6fn4/o6OgqCYqIiIiIiIjoaWDw7eXnz5+X/r58+TJu374tfVer1Th06BCaNGlStdERERERERER1WEGN7rbtWsHmUwGmUym9zZyhUKBdevWVWlwRERERERERHWZwY3u1NRUCCHg6uqK2NhYNGzYUJpnamoKe3t7GBkZVUuQRERERERERHWRwY3u5s2bAwA0Gk21BUNERERERET0NKn0K8MAICUlBatXr0ZSUhIAoHXr1pg5cyZatGhRpcERERERERER1WWVHr388OHDaN26NWJjY9G2bVu0bdsWp0+fhpeXF44ePVodMRIRERERERHVSZXu6Z4/fz5mzZqF//znP6Wmz5s3Dy+99FKVBUdERERERERUl1W6pzspKQnBwcGlpo8fPx6XL1+ukqCIiIiIiIiIngaVbnQ3bNgQCQkJpaYnJCTA3t6+KmIiIiIiIiIieioYfHv54sWLMXfuXISEhGDChAm4fv06unbtCgCIiYnBsmXLMHv27GoLlIiIiIiIiKiuMbjRHR4ejkmTJuG9996DlZUVVq1ahQULFgAAGjdujLCwMMyYMaPaAiUiIiIiIiKqawxudAshAAAymQyzZs3CrFmz8ODBAwCAlZVV9URHREREREREVIdVavRymUym852NbSIiIiIiIqKyVarR3apVq1IN78fdu3fvbwVERERERERE9LSoVKM7PDwc9erVq65YiIiIiIiIiJ4qlWp0v/baa3wtGBEREREREZGBDH5Pd0W3lRMRERERERGRLoMb3drRy4mIiIiIiIjIMAbfXq7RaKozDiIiIiIiIqKnjsE93URERERERERUOWx0ExEREREREVUTNrqJiIiIiIiIqgkb3URERERERETVhI1uIiIiIiIiomrCRjcRERERERFRNWGjm4iIiIiIiKiasNFNREREREREVE3Y6CYiIiIiIiKqJmx0ExEREREREVUTNrqJiIiIiIiIqgkb3URERERERETVhI1uIiIiIiIiomrCRjcRERERERFRNWGjm4iIiIiIiKiasNFNREREREREVE3Y6CYiIiIiIiKqJmx0ExER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7969ERsbi88//7zMgYcep21wN2vWDCtWrEBmZiZu376N27dvG7S8s7MzVCoVjh07hszMTOTl5aFly5YIDAxESEgITp48icTERIwaNQpNmjQptQ2P5xUUFITx48dj7969SE1NRVRUlDQAmSFiY2Ph4eGB9PR0AI8GCjM3N0dQUBAuXryI48ePY/r06Rg9ejQaNfrfowOFhYUIDg7G5cuXcfDgQYSGhmLatGmQy+U4ffo0li5diri4OKSlpWH37t3466+/pAbVnj17pNukAaBly5aIi4vD4cOHceXKFbz33ns4c+ZMqW09f/48kpOTkZmZiaKiIowcORINGjRAYGAgoqOjpe2fMWMGfv/9d4PLYMGCBRgzZkyF6R4+fIhp06YhKioKN2/eRExMDM6cOSNt14IFC3DmzBlMmTIF58+fx2+//Yb169cjMzMT9evXh52dHTZt2oRr167hp59+wuzZs8td39SpU3Hv3j2MGDECZ86cQUpKCg4fPoxx48ZBrVZDqVQiODgYb731Fn766SdcvHgRY8eONbjx5O7ujoCAAEycOBGnT59GfHw83njjDZ0LTb1794a3tzdGjhyJs2fPIjY2FmPGjEH37t2lW7+dnZ2RmpqKhIQEZGZmoqCgwKD1f/fdd/jvf/+LK1euIDQ0FLGxsaUG7HvcW2+9hWXLluGbb75BcnIy5s+fj4SEBMycORMA8Prrr0MmkyEkJETaNx9/lV/nzp1hYWGBd955BykpKfjqq69KDawXGhqKHTt2IDQ0FElJSbhw4YLOHQfOzs74+eefkZ6ejszMzAq3dd68efjll18wbdo0JCQk4OrVq/j+++8r3N6KdO/eHf/617/w6quv4ujRo0hNTcWPP/6IQ4cO6U2/aNEibN++HeHh4bh06RKSkpLw9ddf49133zV4nc2bN4dMJsP+/fvx119/QaVSlZvekH3f3t4eCoVCGiwwOzsbQPUe94bU4VtvvYWIiAisX78eV69exYcffigN8lYZHh4e0kVHQ4+7Ll26YODAgThy5Ahu3LiBX375BQsXLkRcXFyZ62nZsiV2796NhIQEJCYm4vXXXy/V496rVy98/PHHOHfuHOLi4jBp0qRyX8VX2fr+W8p94vspxIHUqKqwjmo31k/tVmtfGSaEEAW5QhQXCKH669G/lRwU7UmU9cqwlJQUERISIlq1aiW9pqlT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",
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import seaborn as sns\n",
+ "import matplotlib.pyplot as plt\n",
+ "\n",
+ "# Make sure the data is sorted by peak_memory for proper line plotting\n",
+ "df_sorted = combined_df.sort_values(by=\"peak_memory\")\n",
+ "\n",
+ "plt.figure(figsize=(10, 6))\n",
+ "sns.lineplot(\n",
+ " data=df_sorted,\n",
+ " x=\"batch_size\",\n",
+ " y=\"total_step_time\",\n",
+ " hue=\"lines\", # One line per ac_mode\n",
+ " marker=\"o\" # Add markers for clarity\n",
+ ")\n",
+ "plt.title(\"Total Step Time vs. Peak Memory by ac_mode\")\n",
+ "plt.xlabel(\"Batch size\") # Adjust label if needed\n",
+ "plt.ylabel(\"Total Step Time (s)\") # Adjust label if needed\n",
+ "plt.grid(True)\n",
+ "plt.tight_layout()\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 125,
+ "metadata": {},
+ "outputs": [
+ {
+ "ename": "KeyError",
+ "evalue": "'compile'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
+ "\u001b[31mKeyError\u001b[39m Traceback (most recent call last)",
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[125]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m \u001b[43mresults_dict\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m\"\u001b[39;49m\u001b[33;43mcompile\u001b[39;49m\u001b[33;43m\"\u001b[39;49m\u001b[43m]\u001b[49m\n",
+ "\u001b[31mKeyError\u001b[39m: 'compile'"
+ ]
+ }
+ ],
+ "source": [
+ "results_dict[\"compile\"]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "modalities_311",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.11.11"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}