def METHOD_NAME(epoch, model, optimizer, _criterion, lr_scheduler, dataloader, booster, coordinator):
    torch.cuda.synchronize()
    use_pipeline = isinstance(booster.plugin, HybridParallelPlugin) and booster.plugin.pp_size > 1
    is_pp_last_stage = use_pipeline and booster.plugin.stage_manager.is_last_stage()
    total_step = len(dataloader)
    model.train()
    optimizer.zero_grad()
    dataloader = iter(dataloader)
    with tqdm(range(total_step), desc=f'Epoch [{epoch + 1}]',
              disable=not (coordinator.is_master() or is_pp_last_stage)) as pbar:
        # Forward pass
        for _ in pbar:
            if use_pipeline:
                outputs = booster.execute_pipeline(dataloader,
                                                   model,
                                                   _criterion,
                                                   optimizer,
                                                   return_loss=True,
                                                   return_outputs=True)
                # Backward and optimize
                if is_pp_last_stage:
                    loss = outputs['loss']
                    pbar.set_postfix({'loss': loss.item()})
            else:
                data = next(dataloader)
                data = move_to_cuda(data)
                outputs = model(**data)
                loss = _criterion(outputs, None)
                # Backward
                booster.backward(loss, optimizer)
                pbar.set_postfix({'loss': loss.item()})
            optimizer.step()
            optimizer.zero_grad()
            lr_scheduler.step()