def METHOD_NAME(config, do_eval=False):
    if paddle.distributed.get_world_size() > 1:
        paddle.distributed.init_parallel_env()
    dataset = MAG240M(config.data_dir, seed=123)
    evaluator = MAG240MEvaluator()
    if paddle.distributed.get_rank() == 0:
        dataset.prepare_data()
    paddle.distributed.barrier
    if paddle.distributed.get_rank() != 0:
        dataset.prepare_data()
    paddle.distributed.barrier
    train_iter = DataGenerator(
        dataset=dataset,
        samples=config.samples,
        batch_size=config.batch_size,
        num_workers=config.num_workers,
        data_type="train")
    valid_iter = DataGenerator(
        dataset=dataset,
        samples=config.samples,
        batch_size=config.batch_size,
        num_workers=config.num_workers,
        data_type="eval")
    model = getattr(models, config.model.name).GNNModel(
        **dict(config.model.items()))
    if paddle.distributed.get_world_size() > 1:
        model = paddle.DataParallel(model)
    loss_func = F.cross_entropy
    opt, lr_scheduler = optim.get_optimizer(
        parameters=model.parameters(),
        learning_rate=config.lr,
        max_steps=config.max_steps,
        weight_decay=config.weight_decay,
        warmup_proportion=config.warmup_proportion,
        clip=config.clip,
        use_lr_decay=config.use_lr_decay)
    _create_if_not_exist(config.output_path)
    #     load_model(config.output_path, model, opt, lr_scheduler)
    load_model(config.output_path, model)
    swriter = SummaryWriter(os.path.join(config.output_path, 'log'))
    if do_eval and paddle.distributed.get_rank() == 0:
        valid_iter = DataGenerator(
            dataset=dataset,
            samples=[160] * len(config.samples),
            batch_size=config.batch_size,
            num_workers=config.num_workers,
            data_type="eval")
        r = evaluate(valid_iter, model, loss_func, config, evaluator, dataset)
        log.info(dict(r))
    else:
        best_valid_acc = -1
        for e_id in range(config.epochs):
            loss_temp = []
            for batch in tqdm.tqdm(train_iter.generator()):
                loss = train_step(model, loss_func, batch, dataset)
                log.info(float(loss))
                loss.backward()
                opt.step()
                if lr_scheduler is not None:
                    lr_scheduler.step()
                opt.clear_gradients()
                loss_temp.append(float(loss))
            loss = np.mean(loss_temp)
            log.info("Epoch %s Train Loss: %s" % (e_id, loss))
            swriter.add_scalar('loss', loss, e_id)
            if e_id >= config.eval_step and  e_id % config.eval_per_steps == 0 and \
                                            paddle.distributed.get_rank() == 0:
                r = evaluate(valid_iter, model, loss_func, config, evaluator,
                             dataset)
                log.info(dict(r))
                for key, value in r.items():
                    swriter.add_scalar('eval/' + key, value, e_id)
                best_valid_acc = max(best_valid_acc, r['acc'])
                if best_valid_acc == r['acc']:
                    save_model(config.output_path, model, e_id, opt,
                               lr_scheduler)
    swriter.close()