Files
2026-07-13 13:17:40 +08:00

124 lines
3.7 KiB
Python

import json
import logging
import os
import pprint
import time
import ray.train
from ray._private.test_utils import safe_write_to_results_json
from ray.train.torch import TorchTrainer
from ray.train.v2._internal.util import date_str
from config import BenchmarkConfig, cli_to_config
from benchmark_factory import BenchmarkFactory
from ray_dataloader_factory import RayDataLoaderFactory
logger = logging.getLogger(__name__)
METRICS_OUTPUT_PATH = "/mnt/cluster_storage/train_benchmark_metrics.json"
def train_fn_per_worker(config):
factory: BenchmarkFactory = config["factory"]
if factory.benchmark_config.task == "recsys":
from recsys.torchrec_runner import TorchRecRunner
runner = TorchRecRunner(factory)
else:
from runner import VanillaTorchRunner
runner = VanillaTorchRunner(factory)
runner.run()
metrics = runner.get_metrics(
dataset_creation_time=config.get("dataset_creation_time", 0)
)
if ray.train.get_context().get_world_rank() == 0:
with open(METRICS_OUTPUT_PATH, "w") as f:
json.dump(metrics, f)
def get_datasets_and_data_config(factory: BenchmarkFactory):
dataloader_factory = factory.get_dataloader_factory()
if isinstance(dataloader_factory, RayDataLoaderFactory):
datasets = dataloader_factory.get_ray_datasets()
data_config = dataloader_factory.get_ray_data_config()
else:
datasets = {}
data_config = None
return datasets, data_config
def main():
start_time = time.perf_counter()
logging.basicConfig(level=logging.INFO)
benchmark_config: BenchmarkConfig = cli_to_config()
logger.info(
"\nBenchmark config:\n" + pprint.pformat(benchmark_config.__dict__, indent=2)
)
if benchmark_config.task == "image_classification":
from image_classification.factory import ImageClassificationFactory
factory = ImageClassificationFactory(benchmark_config)
elif benchmark_config.task == "recsys":
from recsys.recsys_factory import RecsysFactory
factory = RecsysFactory(benchmark_config)
else:
raise ValueError(f"Unknown task: {benchmark_config.task}")
datasets, data_config = get_datasets_and_data_config(factory)
dataset_creation_time = time.perf_counter() - start_time
trainer = TorchTrainer(
train_loop_per_worker=train_fn_per_worker,
train_loop_config={
"factory": factory,
"dataset_creation_time": dataset_creation_time,
},
scaling_config=ray.train.ScalingConfig(
num_workers=benchmark_config.num_workers,
use_gpu=not benchmark_config.mock_gpu,
resources_per_worker={"MOCK_GPU": 1} if benchmark_config.mock_gpu else None,
),
run_config=ray.train.RunConfig(
storage_path=f"{os.environ['ANYSCALE_ARTIFACT_STORAGE']}/train_benchmark/",
name=f"{benchmark_config.task}-{date_str(include_ms=True)}",
failure_config=ray.train.FailureConfig(
max_failures=benchmark_config.max_failures
),
),
datasets=datasets,
dataset_config=data_config,
)
trainer.fit()
end_time = time.perf_counter()
with open(METRICS_OUTPUT_PATH, "r") as f:
metrics = json.load(f)
final_metrics_str = (
f"\nTotal training time: {end_time - start_time} seconds\n"
"Final metrics:\n" + "-" * 80 + "\n" + pprint.pformat(metrics) + "\n" + "-" * 80
)
logger.info(final_metrics_str)
# Write metrics as a release test result.
safe_write_to_results_json(metrics)
if __name__ == "__main__":
# Workers need to access the working directory module.
ray.init(runtime_env={"working_dir": os.path.dirname(__file__)})
main()