一. 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('\nCreat 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()
查看当前所在目录,根据当前目录进行更改即可。 -
同一个文件夹下,文件名和函数名最好别重复,最好别引发歧义。