一. 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()
查看當前所在目錄,根據當前目錄進行更改即可。 -
同一個文件夾下,文件名和函數名最好別重復,最好別引發歧義。