Spaces:
Sleeping
Sleeping
| """ | |
| Data distributed parallel utils. Copied from DINO. | |
| """ | |
| import os | |
| import sys | |
| import time | |
| import math | |
| import random | |
| import datetime | |
| import subprocess | |
| from collections import defaultdict, deque | |
| import numpy as np | |
| import torch | |
| from torch import nn | |
| import torch.distributed as dist | |
| from PIL import ImageFilter, ImageOps | |
| def has_batchnorms(model): | |
| bn_types = (nn.BatchNorm1d, nn.BatchNorm2d, nn.BatchNorm3d, nn.SyncBatchNorm) | |
| for name, module in model.named_modules(): | |
| if isinstance(module, bn_types): | |
| return True | |
| return False | |
| def is_dist_avail_and_initialized(): | |
| if not dist.is_available(): | |
| return False | |
| if not dist.is_initialized(): | |
| return False | |
| return True | |
| def get_world_size(): | |
| if not is_dist_avail_and_initialized(): | |
| return 1 | |
| return dist.get_world_size() | |
| def get_rank(): | |
| if not is_dist_avail_and_initialized(): | |
| return 0 | |
| return dist.get_rank() | |
| def is_main_process(): | |
| return get_rank() == 0 | |
| def save_on_master(*args, **kwargs): | |
| if is_main_process(): | |
| torch.save(*args, **kwargs) | |
| def get_all_gather(tensor): | |
| if not is_dist_avail_and_initialized(): | |
| print("Not in distributed mode.") | |
| return tensor | |
| tensor_list = [tensor.clone() for _ in range(get_world_size())] | |
| dist.all_gather(tensor_list, tensor) | |
| return torch.cat(tensor_list, dim=0) | |
| def setup_for_distributed(is_master): | |
| """ | |
| This function disables printing when not in master process | |
| """ | |
| import builtins as __builtin__ | |
| builtin_print = __builtin__.print | |
| def print(*args, **kwargs): | |
| force = kwargs.pop('force', False) | |
| if is_master or force: | |
| builtin_print(*args, **kwargs) | |
| __builtin__.print = print | |
| def init_distributed_mode(): | |
| # launched with `torch.distributed.launch` | |
| if 'RANK' in os.environ and 'WORLD_SIZE' in os.environ: | |
| # 当前处于某个进程中, 配置当前进程的环境参数 | |
| rank = int(os.environ["RANK"]) | |
| world_size = int(os.environ['WORLD_SIZE']) | |
| gpu = int(os.environ['LOCAL_RANK']) | |
| # launched naively with `python main.py` | |
| elif torch.cuda.is_available(): | |
| print('Will run the code on one GPU.') | |
| rank, gpu, world_size = 0, 0, 1 | |
| os.environ['MASTER_ADDR'] = '127.0.0.1' # 针对单机单卡的情况设置通信地址和端口 | |
| os.environ['MASTER_PORT'] = '29500' | |
| else: | |
| print('Does not support training without GPU.') | |
| sys.exit(1) | |
| dist.init_process_group( | |
| backend="nccl", # 后端通信采用 NVIDIA 的推荐协议 | |
| init_method='env://', # 使用环境变量初始化 (MASTER_PORT, MASTER_ADDR) | |
| world_size=world_size, # 总进程数 | |
| rank=rank, # 当前进程序号 | |
| ) | |
| torch.cuda.set_device(gpu) # 设置当前节点 local_rank 对应的 GPU id | |
| print('| distributed init (rank {}): {}'.format(rank, "env://"), flush=True) | |
| dist.barrier() # 同步屏障, 所有节点启动后才进入下一句 | |
| setup_for_distributed(rank == 0) | |
| print("MASTER ADDR, PORT: {}:{}".format(os.environ['MASTER_ADDR'], os.environ['MASTER_PORT'])) | |