code: def test_epoch_sync(self, tmp_path: pathlib.Path, dataset_len: int):
      num_procs = 2
  
      launch_config = pytorch_utils.setup_torch_distributed(
          local_procs=num_procs
      )
  
      num_steps = 10
      global_batch_size = 2
      outputs = launcher.elastic_launch(launch_config, run_no_op)(
          tmp_path, num_steps, global_batch_size, dataset_len
      )
  
      log_output = sum([outputs[i] for i in range(num_procs)], [])
  
      batches_per_epoch = (
          dataset_len + global_batch_size - 1
      ) // global_batch_size  # ceil
  
      patterns = []
      for rank in range(num_procs):
          for batch_idx in range(num_steps):
              epoch_idx = batch_idx // batches_per_epoch
              patterns.append(
                  f"rank {rank} finished batch {batch_idx} in epoch {epoch_idx}"
              )
  
      utils.assert_patterns_in_logs(log_output, patterns)
  
imports: import contextlib
  import importlib
  import io
  import os
  import pathlib
  import sys
  import typing
  from unittest import mock
  import numpy
  import pytest
  import torch
  from _pytest import monkeypatch
  from torch.distributed import launcher
  import determined
  from determined import pytorch
  from tests.experiment import pytorch_utils, utils
  from tests.experiment.fixtures import pytorch_onevar_model
label_desc: Use image node_id 30 for calling the TestPyTorchTrial obj's underlying member method code with example usage: obj.test_epoch_sync(tmp_path, dataset_len) without return types