工作小结五

一. torch数据并行

DataParallel是单进程,多线程情况,DistributedDataParallel支持多进程多线程(当然你可以当做单进程多线程使用)。

关于更细致的解释不多说:参考

关于进程的执行:

  • 粗暴的方式,直接在多个命令行执行多个python train.py --rank 0,通过命令行参数控制进程的ID。比如torch的多进程通过控制rank控制ID,通讯端口相同,解码器相同,这里代码参考:代码
def main():  
    parser = argparse.ArgumentParser()  
    parser.add_argument('-n', '--nodes', default=1,  
                        type=int, metavar='N')  
    parser.add_argument('-g', '--gpus', default=1, type=int,  
                        help='number of gpus per node')  
    parser.add_argument('-nr', '--nr', default=0, type=int,  
                        help='ranking within the nodes')  
    parser.add_argument('--epochs', default=2, type=int,  
                        metavar='N',  
                        help='number of total epochs to run')  
    args = parser.parse_args()  
    #########################################################  
    args.world_size = args.gpus * args.nodes                #  
    os.environ['MASTER_ADDR'] = '10.57.23.164'              #  
    os.environ['MASTER_PORT'] = '8888'                      #  
    mp.spawn(train, nprocs=args.gpus, args=(args,))         #  
    #########################################################  
  • 通过python自带的multiprocessing执行多进程,通过一个循环执行和传入的参数执行不同的ID。这里参考官方代码,已修改部分代码代码
def main():
    #args = parse_args()
    #update_config(cfg, args)

    cudnn.deterministic = cfg.SYSTEM.DETERMINISTIC

    if cfg.TRAIN.DIST.IS_MULTI_DISTRIBUTE:
        # Use torch.multiprocessing.spawn to launch distributed processes: the
        # main_worker process function
        mp.spawn(main_worker, nprocs=len(cfg.SYSTEM.GPU_ID), args=())
    else:
        # Simply call main_worker function
        main_worker(cfg.SYSTEM.GPU_ID)
def main_worker(cur_gpu):
    global models#, g_rank, g_batch, g_numwork, logger

    # Since we have ngpus_per_node processes per node, the total world_size
    # needs to be adjusted accordingly
    cfg.TRAIN.DIST.WORLD_SIZE = len(cfg.SYSTEM.GPU_ID) * cfg.TRAIN.DIST.WORLD_SIZE #FIXME get error when put out side

    if cfg.TRAIN.DIST.IS_MULTI_DISTRIBUTE:
        # For multiprocessing distributed training, rank needs to be the
        # global rank among all the processes
        cfg.TRAIN.DIST.RANK = cfg.TRAIN.DIST.RANK * len(cfg.SYSTEM.GPU_ID) + cur_gpu
        dist.init_process_group(backend=cfg.TRAIN.DIST.BACKEND,
                                init_method=cfg.TRAIN.DIST.METHOD,
                                world_size=cfg.TRAIN.DIST.WORLD_SIZE,
                                rank=cfg.TRAIN.DIST.RANK)

    if cfg.TRAIN.IS_LOAD_PRETRAINED:
        models.load_state_dict(torch.load(cfg.FILE.PRETRAINED,map_location=torch.device('cpu')))

    if cfg.TRAIN.DIST.IS_MULTI_DISTRIBUTE:
        # For multiprocessing distributed, DistributedDataParallel constructor
        # should always set the single device scope, otherwise,
        # DistributedDataParallel will use all available devices.
        torch.cuda.set_device(cur_gpu)
        models.cuda(cur_gpu)
        # When using a single GPU per process and per
        # DistributedDataParallel, we need to divide the batch size
        # ourselves based on the total number of GPUs we have
        cfg.TRAIN.BATCH_SIZE = int(cfg.TRAIN.BATCH_SIZE / len(cfg.SYSTEM.GPU_ID))
        cfg.SYSTEM.NUM_WORKERS = int((cfg.SYSTEM.NUM_WORKERS + len(cfg.SYSTEM.GPU_ID) - 1) / len(cfg.SYSTEM.GPU_ID))
        models = torch.nn.parallel.DistributedDataParallel(models, device_ids=[cur_gpu])
        logger.info('
Creat process world size:{}, rank:{}, gpu:{}, num_work:{}, batch_sieze:{} ' 
                    .format(cfg.TRAIN.DIST.WORLD_SIZE, 
                            cfg.TRAIN.DIST.RANK, cur_gpu,
                            cfg.SYSTEM.NUM_WORKERS,
                            cfg.TRAIN.BATCH_SIZE))
    else :
        models = models.cuda(cur_gpu[0])
        models = nn.DataParallel(models, device_ids=cur_gpu)

    train_sampler = None
    if cfg.TRAIN.DIST.IS_MULTI_DISTRIBUTE:
        train_sampler = torch.utils.data.distributed.DistributedSampler(
                                RHDDataset(dataset_dir=cfg.DATASET.RHD_HAND.DATA_ROOT, is_train=True))
    train_loader = DataLoaderX(
                                RHDDataset(dataset_dir=cfg.DATASET.RHD_HAND.DATA_ROOT, is_train=True),
                                shuffle = True if train_sampler is None else False,
                                pin_memory=cfg.SYSTEM.PIN_MEMORY,
                                batch_size=cfg.TRAIN.BATCH_SIZE,
                                num_workers=cfg.SYSTEM.NUM_WORKERS,
                                sampler=train_sampler)
    optimizer = optim.Adam(params=models.parameters(), lr=cfg.TRAIN.LR_RATE)
    scheduler = WarmupCosineLR()
    cudnn.benchmark = True
    
    #Train epochs
    #........

关于注意事项:

  • torch已经封装的很好了,而且还有demo。其实仅仅修改batchsize和rank即可,代码很简单。
  • 注意GPU的数量,前面使用os.environ去控制一下比较好。
  • 我这里看单进程4GPU:大概75%的利用率,四进程4GPU:大概85%的利用率。抖动有点严重,有时候60%-99%,看数据分散情况。

二. No Modules

关于No Moudules,这个不同编译器不同。

关于VScode:

  • 安装python或conda环境之后,提示找不到python或者找不到XXX modules,比如python-opencv在命令行可以使用,但是在vscode显示找不到cv2.

使用sys.executable查看当前的python环境,看看是不是你使用的环境?

如果不是,那三种方法:

如果当前环境没错,看看模块名是不是和文件名重复了(尽量别重复)。
F5调试,然后在错误的地方F11进入(进不了说明os.getcwd()有问题,自己检查项目根目录),查看内部具体是哪个import有问题,针对修改即可。

如果上面都完成解决不了,那就自己强制加一句话:"env": {"PYTHONPATH":"${workspaceRoot}"}
如果是debug,那就在debug的launch.json里面加。如果是run,那就在.vscode目录下的文件夹,launch.json里面加。

关于pycharm

  • 设置中的环境不能弄错。

  • 使用os.getpwd()查看当前所在目录,根据当前目录进行更改即可。

  • 同一个文件夹下,文件名和函数名最好别重复,最好别引发歧义。

原文地址:https://www.cnblogs.com/wjy-lulu/p/13083600.html