openpoints 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openpoints/__init__.py +3 -0
- openpoints/cpp/__init__.py +6 -0
- openpoints/cpp/chamfer_dist/__init__.py +110 -0
- openpoints/cpp/chamfer_dist/setup.py +19 -0
- openpoints/cpp/chamfer_dist/test.py +34 -0
- openpoints/cpp/emd/__init__.py +3 -0
- openpoints/cpp/emd/emd.py +88 -0
- openpoints/cpp/emd/setup.py +27 -0
- openpoints/cpp/emd/test_emd_loss.py +45 -0
- openpoints/cpp/pointnet2_batch/__init__.py +24 -0
- openpoints/cpp/pointnet2_batch/setup.py +23 -0
- openpoints/cpp/pointops/__init__.py +0 -0
- openpoints/cpp/pointops/functions/__init__.py +0 -0
- openpoints/cpp/pointops/functions/pointops.py +314 -0
- openpoints/cpp/pointops/setup.py +37 -0
- openpoints/cpp/pointops/src/__init__.py +0 -0
- openpoints/dataset/__init__.py +10 -0
- openpoints/dataset/atom3d/__init__.py +1 -0
- openpoints/dataset/atom3d/psr.py +38 -0
- openpoints/dataset/build.py +98 -0
- openpoints/dataset/data_util.py +192 -0
- openpoints/dataset/datalist.py +67 -0
- openpoints/dataset/dataset_base.py +96 -0
- openpoints/dataset/graph_dataset/__init__.py +3 -0
- openpoints/dataset/graph_dataset/graph_dataset.py +93 -0
- openpoints/dataset/graph_dataset/stack_with_pad.py +91 -0
- openpoints/dataset/graph_dataset/structural_dataset.py +73 -0
- openpoints/dataset/graph_dataset/svd_encodings_dataset.py +110 -0
- openpoints/dataset/grid_sample.py +21 -0
- openpoints/dataset/matterport3d/__init__.py +1 -0
- openpoints/dataset/matterport3d/category_mapping.tsv +1660 -0
- openpoints/dataset/matterport3d/matterport3d.py +210 -0
- openpoints/dataset/matterport3d/matterport3d_dataprocessing.py +105 -0
- openpoints/dataset/modelnet/__init__.py +3 -0
- openpoints/dataset/modelnet/modelnet40_normal_resampled_loader.py +124 -0
- openpoints/dataset/modelnet/modelnet40_ply_2048_loader.py +160 -0
- openpoints/dataset/molhiv/__init__.py +1 -0
- openpoints/dataset/molhiv/data.py +59 -0
- openpoints/dataset/molpcba/__init__.py +1 -0
- openpoints/dataset/molpcba/data.py +59 -0
- openpoints/dataset/parsers/__init__.py +1 -0
- openpoints/dataset/parsers/class_map.py +19 -0
- openpoints/dataset/parsers/constants.py +1 -0
- openpoints/dataset/parsers/parser.py +17 -0
- openpoints/dataset/parsers/parser_factory.py +29 -0
- openpoints/dataset/parsers/parser_image_folder.py +69 -0
- openpoints/dataset/parsers/parser_image_in_tar.py +222 -0
- openpoints/dataset/parsers/parser_image_tar.py +72 -0
- openpoints/dataset/parsers/parser_tfds.py +297 -0
- openpoints/dataset/pcqm4m/__init__.py +1 -0
- openpoints/dataset/pcqm4m/data.py +62 -0
- openpoints/dataset/pcqm4mv2/__init__.py +1 -0
- openpoints/dataset/pcqm4mv2/data.py +87 -0
- openpoints/dataset/s3dis/__init__.py +2 -0
- openpoints/dataset/s3dis/s3dis.py +156 -0
- openpoints/dataset/s3dis/s3dis_block.py +96 -0
- openpoints/dataset/s3dis/s3dis_sphere.py +349 -0
- openpoints/dataset/scannetv2/__init__.py +1 -0
- openpoints/dataset/scannetv2/scannet.py +176 -0
- openpoints/dataset/scanobjectnn/__init__.py +3 -0
- openpoints/dataset/scanobjectnn/scanobjectnn.py +110 -0
- openpoints/dataset/semantic_kitti/__init__.py +1 -0
- openpoints/dataset/semantic_kitti/helper_tool.py +286 -0
- openpoints/dataset/semantic_kitti/label_mapping.yaml +211 -0
- openpoints/dataset/semantic_kitti/semantickitti.py +229 -0
- openpoints/dataset/semantic_kitti/utils/meta/anno_paths.txt +272 -0
- openpoints/dataset/semantic_kitti/utils/meta/class_names.txt +13 -0
- openpoints/dataset/semantic_kitti/utils/semantic-kitti.yaml +211 -0
- openpoints/dataset/shapenet/__init__.py +1 -0
- openpoints/dataset/shapenet/shapenet55.py +76 -0
- openpoints/dataset/shapenet/shapenetpart.py +121 -0
- openpoints/dataset/shapenetpart/__init__.py +1 -0
- openpoints/dataset/shapenetpart/shapenet55.py +75 -0
- openpoints/dataset/shapenetpart/shapenetpart.py +388 -0
- openpoints/dataset/vis2d.py +17 -0
- openpoints/dataset/vis3d.py +153 -0
- openpoints/loss/__init__.py +3 -0
- openpoints/loss/build.py +281 -0
- openpoints/loss/cross_entropy.py +38 -0
- openpoints/loss/distill_loss.py +76 -0
- openpoints/models/__init__.py +10 -0
- openpoints/models/backbone/Stratified_transformer.py +558 -0
- openpoints/models/backbone/__init__.py +11 -0
- openpoints/models/backbone/baafnet.py +527 -0
- openpoints/models/backbone/ball_dgcnn.py +123 -0
- openpoints/models/backbone/curvenet.py +793 -0
- openpoints/models/backbone/debug_invvit.py +114 -0
- openpoints/models/backbone/deepgcn.py +143 -0
- openpoints/models/backbone/dgcnn.py +119 -0
- openpoints/models/backbone/graphvit3d.py +134 -0
- openpoints/models/backbone/grouppointnet.py +100 -0
- openpoints/models/backbone/pct.py +163 -0
- openpoints/models/backbone/pointmlp.py +417 -0
- openpoints/models/backbone/pointnet.py +199 -0
- openpoints/models/backbone/pointnetv2.py +511 -0
- openpoints/models/backbone/pointnext.py +663 -0
- openpoints/models/backbone/pointnextPyG.py +555 -0
- openpoints/models/backbone/pointtransformer.py +293 -0
- openpoints/models/backbone/pointvector.py +853 -0
- openpoints/models/backbone/pointvit.py +392 -0
- openpoints/models/backbone/pointvit_inv.py +942 -0
- openpoints/models/backbone/pointvit_inv_old.py +784 -0
- openpoints/models/backbone/randlenet.py +318 -0
- openpoints/models/backbone/resnet.py +342 -0
- openpoints/models/backbone/simpleview.py +153 -0
- openpoints/models/backbone/simpleview_util.py +292 -0
- openpoints/models/build.py +13 -0
- openpoints/models/classification/__init__.py +5 -0
- openpoints/models/classification/cls_base.py +136 -0
- openpoints/models/classification/point_bert.py +154 -0
- openpoints/models/layers/__init__.py +14 -0
- openpoints/models/layers/activation.py +57 -0
- openpoints/models/layers/attention.py +103 -0
- openpoints/models/layers/conv.py +167 -0
- openpoints/models/layers/drop.py +164 -0
- openpoints/models/layers/graph_conv.py +122 -0
- openpoints/models/layers/group.py +415 -0
- openpoints/models/layers/group_embed.py +286 -0
- openpoints/models/layers/helpers.py +43 -0
- openpoints/models/layers/kmeans.py +119 -0
- openpoints/models/layers/knn.py +110 -0
- openpoints/models/layers/local_aggregation.py +286 -0
- openpoints/models/layers/mlp.py +129 -0
- openpoints/models/layers/norm.py +106 -0
- openpoints/models/layers/padding.py +56 -0
- openpoints/models/layers/patch_embed.py +37 -0
- openpoints/models/layers/registry.py +168 -0
- openpoints/models/layers/subsample.py +185 -0
- openpoints/models/layers/upsampling.py +106 -0
- openpoints/models/layers/weight_init.py +89 -0
- openpoints/models/reconstruction/__init__.py +8 -0
- openpoints/models/reconstruction/base_recontruct.py +216 -0
- openpoints/models/reconstruction/maskedpoint.py +116 -0
- openpoints/models/reconstruction/maskedpointgroup.py +168 -0
- openpoints/models/reconstruction/maskedpointvit.py +253 -0
- openpoints/models/reconstruction/nodeshuffle.py +11 -0
- openpoints/models/registry.py +149 -0
- openpoints/models/segmentation/__init__.py +6 -0
- openpoints/models/segmentation/base_seg.py +278 -0
- openpoints/models/segmentation/vit_seg.py +126 -0
- openpoints/optim/__init__.py +15 -0
- openpoints/optim/adabelief.py +201 -0
- openpoints/optim/adafactor.py +167 -0
- openpoints/optim/adahessian.py +156 -0
- openpoints/optim/adamp.py +105 -0
- openpoints/optim/adamw.py +122 -0
- openpoints/optim/lamb.py +192 -0
- openpoints/optim/lars.py +135 -0
- openpoints/optim/lookahead.py +61 -0
- openpoints/optim/madgrad.py +184 -0
- openpoints/optim/nadam.py +92 -0
- openpoints/optim/nvnovograd.py +120 -0
- openpoints/optim/optim_factory.py +306 -0
- openpoints/optim/radam.py +89 -0
- openpoints/optim/rmsprop_tf.py +139 -0
- openpoints/optim/sgdp.py +70 -0
- openpoints/scheduler/__init__.py +8 -0
- openpoints/scheduler/cosine_lr.py +124 -0
- openpoints/scheduler/multistep_lr.py +65 -0
- openpoints/scheduler/plateau_lr.py +113 -0
- openpoints/scheduler/poly_lr.py +116 -0
- openpoints/scheduler/scheduler.py +110 -0
- openpoints/scheduler/scheduler_factory.py +118 -0
- openpoints/scheduler/step_lr.py +65 -0
- openpoints/scheduler/tanh_lr.py +117 -0
- openpoints/transforms/__init__.py +7 -0
- openpoints/transforms/point_transform_cpu.py +332 -0
- openpoints/transforms/point_transformer_gpu.py +764 -0
- openpoints/transforms/transforms_factory.py +60 -0
- openpoints/utils/__init__.py +8 -0
- openpoints/utils/ckpt_util.py +438 -0
- openpoints/utils/config.py +113 -0
- openpoints/utils/dist_utils.py +54 -0
- openpoints/utils/logger.py +170 -0
- openpoints/utils/metrics.py +311 -0
- openpoints/utils/random.py +16 -0
- openpoints/utils/registry.py +294 -0
- openpoints/utils/str2bool.py +11 -0
- openpoints/utils/wandb.py +88 -0
- openpoints-0.1.0.dist-info/METADATA +150 -0
- openpoints-0.1.0.dist-info/RECORD +184 -0
- openpoints-0.1.0.dist-info/WHEEL +5 -0
- openpoints-0.1.0.dist-info/licenses/LICENSE +21 -0
- openpoints-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
from ..utils.registry import Registry
|
|
3
|
+
|
|
4
|
+
DataTransforms = Registry('datatransforms')
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def concat_collate_fn(datas):
|
|
8
|
+
"""collate fn for point transformer
|
|
9
|
+
"""
|
|
10
|
+
pts, feats, labels, offset, count = [], [], [], [], 0
|
|
11
|
+
for data in datas:
|
|
12
|
+
count += len(data['pos'])
|
|
13
|
+
offset.append(count)
|
|
14
|
+
pts.append(data['pos'])
|
|
15
|
+
feats.append(data['x'])
|
|
16
|
+
labels.append(data['y'])
|
|
17
|
+
data = {'pos': torch.cat(pts), 'x': torch.cat(feats), 'y': torch.cat(labels),
|
|
18
|
+
'o': torch.IntTensor(offset)}
|
|
19
|
+
return data
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class Compose(object):
|
|
23
|
+
"""Composes several transforms together."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, transforms):
|
|
26
|
+
self.transforms = transforms
|
|
27
|
+
|
|
28
|
+
def __call__(self, args):
|
|
29
|
+
for t in self.transforms:
|
|
30
|
+
args = t(args)
|
|
31
|
+
return args
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ListCompose(object):
|
|
35
|
+
def __init__(self, transforms):
|
|
36
|
+
self.transforms = transforms
|
|
37
|
+
|
|
38
|
+
def __call__(self, coord, feat, label):
|
|
39
|
+
for t in self.transforms:
|
|
40
|
+
coord, feat, label = t(coord, feat, label)
|
|
41
|
+
return coord, feat, label
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def build_transforms_from_cfg(split, datatransforms_cfg):
|
|
45
|
+
"""
|
|
46
|
+
Build a dataset transform for a certrain split, defined by `datatransforms_cfg`.
|
|
47
|
+
"""
|
|
48
|
+
transform_list = datatransforms_cfg.get(split, None)
|
|
49
|
+
transform_args = datatransforms_cfg.get('kwargs', None)
|
|
50
|
+
compose_fn = eval(datatransforms_cfg.get('compose_fn', 'Compose'))
|
|
51
|
+
if transform_list is None or len(transform_list) == 0:
|
|
52
|
+
return None
|
|
53
|
+
point_transforms = []
|
|
54
|
+
if len(transform_list) > 1:
|
|
55
|
+
for t in transform_list:
|
|
56
|
+
point_transforms.append(DataTransforms.build(
|
|
57
|
+
{'NAME': t}, default_args=transform_args))
|
|
58
|
+
return compose_fn(point_transforms)
|
|
59
|
+
else:
|
|
60
|
+
return DataTransforms.build({'NAME': transform_list[0]}, default_args=transform_args)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
from .random import set_random_seed
|
|
2
|
+
from .config import EasyConfig, print_args
|
|
3
|
+
from .logger import setup_logger_dist, generate_exp_directory, resume_exp_directory
|
|
4
|
+
from .wandb import Wandb
|
|
5
|
+
from .metrics import AverageMeter, ConfusionMatrix, get_mious
|
|
6
|
+
from .ckpt_util import resume_model, resume_optimizer, resume_checkpoint, save_checkpoint, load_checkpoint, \
|
|
7
|
+
get_missing_parameters_message, get_unexpected_parameters_message, cal_model_parm_nums, load_checkpoint_inv
|
|
8
|
+
from .dist_utils import reduce_tensor, gather_tensor, find_free_port
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os, shutil
|
|
3
|
+
from termcolor import colored
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Optional, List, Dict, NamedTuple, Tuple, Iterable
|
|
6
|
+
from collections import OrderedDict, defaultdict
|
|
7
|
+
import torch
|
|
8
|
+
import torch.nn as nn
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ================ model related ==================
|
|
12
|
+
def cal_model_parm_nums(model):
|
|
13
|
+
total = sum([param.nelement() for param in model.parameters()])
|
|
14
|
+
return total
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def resume_model(model, cfg, pretrained_path=None):
|
|
18
|
+
pretrained_path = os.path.join(cfg.ckpt_dir, os.path.join(cfg.run_name,
|
|
19
|
+
'_ckpt_latest.pth')) if pretrained_path is None else pretrained_path
|
|
20
|
+
if not os.path.exists(pretrained_path):
|
|
21
|
+
logging.info(f'[RESUME INFO] no checkpoint file from path {pretrained_path}...')
|
|
22
|
+
return 0, 0
|
|
23
|
+
logging.info(f'[RESUME INFO] Loading model weights from {pretrained_path}...')
|
|
24
|
+
|
|
25
|
+
# load state dict
|
|
26
|
+
state_dict = torch.load(pretrained_path, map_location='cpu')
|
|
27
|
+
# parameter resume of base model
|
|
28
|
+
base_ckpt = {k.replace("module.", ""): v for k, v in state_dict['model'].items()}
|
|
29
|
+
model.load_state_dict(base_ckpt, strict=True)
|
|
30
|
+
|
|
31
|
+
# parameter
|
|
32
|
+
if 'epoch' in state_dict.keys():
|
|
33
|
+
start_epoch = state_dict['epoch'] + 1
|
|
34
|
+
else:
|
|
35
|
+
start_epoch = 1
|
|
36
|
+
if 'best_metrics' in state_dict.keys():
|
|
37
|
+
best_metrics = state_dict['best_metrics']
|
|
38
|
+
if not isinstance(best_metrics, dict):
|
|
39
|
+
best_metrics = best_metrics.state_dict()
|
|
40
|
+
else:
|
|
41
|
+
best_metrics = None
|
|
42
|
+
|
|
43
|
+
logging.info(f'[RESUME INFO] resume ckpts @ {start_epoch - 1} epoch( best_metrics = {str(best_metrics):s})')
|
|
44
|
+
return start_epoch, best_metrics
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def resume_optimizer(cfg, optimizer, pretrained_path=None):
|
|
48
|
+
pretrained_path = os.path.join(cfg.ckpt_dir, os.path.join(cfg.run_name,
|
|
49
|
+
'_ckpt_latest.pth')) if pretrained_path is None else pretrained_path
|
|
50
|
+
if not os.path.exists(pretrained_path):
|
|
51
|
+
logging.info(f'[RESUME INFO] no checkpoint file from path {pretrained_path}...')
|
|
52
|
+
return 0, 0, 0
|
|
53
|
+
logging.info(f'[RESUME INFO] Loading optimizer from {pretrained_path}...')
|
|
54
|
+
# load state dict
|
|
55
|
+
state_dict = torch.load(pretrained_path, map_location='cpu')
|
|
56
|
+
# optimizer
|
|
57
|
+
if state_dict['optimizer'] is not None and state_dict['optimizer']:
|
|
58
|
+
optimizer.load_state_dict(state_dict['optimizer'])
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def save_checkpoint(cfg, model, epoch, optimizer=None, scheduler=None,
|
|
62
|
+
additioanl_dict=None,
|
|
63
|
+
is_best=False, post_fix='ckpt_latest', save_name=None, ):
|
|
64
|
+
if save_name is None:
|
|
65
|
+
save_name = cfg.run_name
|
|
66
|
+
|
|
67
|
+
current_ckpt_name = f'{save_name}_{post_fix}.pth'
|
|
68
|
+
current_pretrained_path = os.path.join(cfg.ckpt_dir, current_ckpt_name)
|
|
69
|
+
save_dict = {
|
|
70
|
+
'model': model.module.state_dict() if hasattr(model, 'module') else model.state_dict(),
|
|
71
|
+
'optimizer': optimizer.state_dict() if optimizer is not None else dict(),
|
|
72
|
+
'scheduler': scheduler.state_dict() if scheduler is not None else dict(),
|
|
73
|
+
'epoch': epoch
|
|
74
|
+
}
|
|
75
|
+
if additioanl_dict is not None:
|
|
76
|
+
save_dict.update(additioanl_dict)
|
|
77
|
+
|
|
78
|
+
torch.save(save_dict, current_pretrained_path)
|
|
79
|
+
|
|
80
|
+
if cfg.save_freq > 0 and epoch % cfg.save_freq == 0:
|
|
81
|
+
milestone_ckpt_name = f'{save_name}_E{epoch}.pth'
|
|
82
|
+
milestone_pretrained_path = os.path.join(cfg.ckpt_dir, milestone_ckpt_name)
|
|
83
|
+
shutil.copyfile(current_pretrained_path, milestone_pretrained_path)
|
|
84
|
+
logging.info("Saved in {}".format(milestone_pretrained_path))
|
|
85
|
+
|
|
86
|
+
if is_best:
|
|
87
|
+
best_ckpt_name = f'{save_name}_ckpt_best.pth' if save_name else 'ckpt_best.pth'
|
|
88
|
+
best_pretrained_path = os.path.join(cfg.ckpt_dir, best_ckpt_name)
|
|
89
|
+
shutil.copyfile(current_pretrained_path, best_pretrained_path)
|
|
90
|
+
logging.info("Found the best model and saved in {}".format(best_pretrained_path))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def resume_checkpoint(config, model, optimizer=None, scheduler=None, pretrained_path=None, printer=logging.info):
|
|
94
|
+
if pretrained_path is None:
|
|
95
|
+
pretrained_path = config.pretrained_path
|
|
96
|
+
assert pretrained_path is not None
|
|
97
|
+
printer("=> loading checkpoint '{}'".format(pretrained_path))
|
|
98
|
+
|
|
99
|
+
checkpoint = torch.load(pretrained_path, map_location='cpu')
|
|
100
|
+
config.start_epoch = checkpoint['epoch'] + 1
|
|
101
|
+
if optimizer is not None:
|
|
102
|
+
try:
|
|
103
|
+
optimizer.load_state_dict(checkpoint['optimizer'])
|
|
104
|
+
except:
|
|
105
|
+
printer('optimizer does not match')
|
|
106
|
+
if scheduler is not None:
|
|
107
|
+
try:
|
|
108
|
+
scheduler.load_state_dict(checkpoint['scheduler'])
|
|
109
|
+
except:
|
|
110
|
+
printer('scheduler does not match')
|
|
111
|
+
|
|
112
|
+
ckpt_state = checkpoint['model']
|
|
113
|
+
model_dict = model.state_dict()
|
|
114
|
+
# rename ckpt (avoid name is not same because of multi-gpus)
|
|
115
|
+
is_model_multi_gpus = True if list(model_dict)[0].split('.')[0] == 'module' else False
|
|
116
|
+
is_ckpt_multi_gpus = True if list(ckpt_state)[0].split('.')[0] == 'module' else False
|
|
117
|
+
|
|
118
|
+
if not (is_model_multi_gpus == is_ckpt_multi_gpus):
|
|
119
|
+
temp_dict = OrderedDict()
|
|
120
|
+
for k, v in ckpt_state.items():
|
|
121
|
+
if is_ckpt_multi_gpus:
|
|
122
|
+
name = k[7:] # remove 'module.'
|
|
123
|
+
else:
|
|
124
|
+
name = 'module.' + k # add 'module'
|
|
125
|
+
temp_dict[name] = v
|
|
126
|
+
ckpt_state = temp_dict
|
|
127
|
+
|
|
128
|
+
model.load_state_dict(ckpt_state)
|
|
129
|
+
|
|
130
|
+
config.start_epoch = checkpoint['epoch'] + 1
|
|
131
|
+
config.epoch = checkpoint['epoch'] + 1
|
|
132
|
+
printer("=> loaded successfully '{}' (epoch {})".format(pretrained_path, checkpoint['epoch']))
|
|
133
|
+
del checkpoint
|
|
134
|
+
torch.cuda.empty_cache()
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def load_checkpoint(model, pretrained_path, module=None):
|
|
138
|
+
if not os.path.exists(pretrained_path):
|
|
139
|
+
raise NotImplementedError('no checkpoint file from path %s...' % pretrained_path)
|
|
140
|
+
# load state dict
|
|
141
|
+
state_dict = torch.load(pretrained_path, map_location='cpu')
|
|
142
|
+
|
|
143
|
+
# parameter resume of base model
|
|
144
|
+
ckpt_state_dict = state_dict
|
|
145
|
+
for key in state_dict.keys():
|
|
146
|
+
if key in ['model', 'net', 'network', 'state_dict', 'base_model']:
|
|
147
|
+
ckpt_state_dict = ckpt_state_dict[key]
|
|
148
|
+
base_ckpt = {k.replace("module.", ""): v for k, v in ckpt_state_dict.items()}
|
|
149
|
+
if module is not None:
|
|
150
|
+
base_ckpt = {k:v for k, v in base_ckpt.items() if module in k}
|
|
151
|
+
|
|
152
|
+
if "bert" in list(ckpt_state_dict.items())[0][0]:
|
|
153
|
+
base_ckpt=bert2vit_ckpt_rename(ckpt_state_dict)
|
|
154
|
+
#state_dict has "qkv.value" key, will be mis-regonized as metric and over flush the command ouput
|
|
155
|
+
state_dict=base_ckpt
|
|
156
|
+
|
|
157
|
+
if hasattr(model, 'module'):
|
|
158
|
+
incompatible = model.module.load_state_dict(base_ckpt, strict=False)
|
|
159
|
+
else:
|
|
160
|
+
incompatible = model.load_state_dict(base_ckpt, strict=False)
|
|
161
|
+
|
|
162
|
+
if incompatible.missing_keys:
|
|
163
|
+
logging.info('missing_keys')
|
|
164
|
+
logging.info(
|
|
165
|
+
get_missing_parameters_message(incompatible.missing_keys),
|
|
166
|
+
)
|
|
167
|
+
if incompatible.unexpected_keys:
|
|
168
|
+
logging.info('unexpected_keys')
|
|
169
|
+
logging.info(
|
|
170
|
+
get_unexpected_parameters_message(incompatible.unexpected_keys)
|
|
171
|
+
)
|
|
172
|
+
logging.info(f'Successful Loading the ckpt from {pretrained_path}')
|
|
173
|
+
|
|
174
|
+
epoch = state_dict.get('epoch', -1)
|
|
175
|
+
metrics = {}
|
|
176
|
+
for key in state_dict.keys():
|
|
177
|
+
is_metric_key = sum([item in key for item in ['metric', 'acc', 'test', 'val']]) > 0
|
|
178
|
+
if is_metric_key:
|
|
179
|
+
metrics[key] = state_dict[key]
|
|
180
|
+
logging.info(f'ckpts @ {epoch} epoch( {metrics} )')
|
|
181
|
+
return epoch, metrics
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def load_checkpoint_inv(model, pretrained_path, module=None):
|
|
186
|
+
if not os.path.exists(pretrained_path):
|
|
187
|
+
raise NotImplementedError('no checkpoint file from path %s...' % pretrained_path)
|
|
188
|
+
# load state dict
|
|
189
|
+
state_dict = torch.load(pretrained_path, map_location='cpu')
|
|
190
|
+
|
|
191
|
+
# parameter resume of base model
|
|
192
|
+
ckpt_state_dict = state_dict
|
|
193
|
+
for key in state_dict.keys():
|
|
194
|
+
if key in ['model', 'net', 'network', 'state_dict', 'base_model']:
|
|
195
|
+
ckpt_state_dict = ckpt_state_dict[key]
|
|
196
|
+
base_ckpt = {k.replace("module.", ""): v for k, v in ckpt_state_dict.items()}
|
|
197
|
+
if module is not None:
|
|
198
|
+
base_ckpt = {k:v for k, v in base_ckpt.items() if module in k}
|
|
199
|
+
|
|
200
|
+
if "bert" in list(ckpt_state_dict.items())[0][0]:
|
|
201
|
+
base_ckpt=bert2vit_ckpt_rename(ckpt_state_dict)
|
|
202
|
+
#state_dict has "qkv.value" key, will be mis-regonized as metric and over flush the command ouput
|
|
203
|
+
state_dict=base_ckpt
|
|
204
|
+
|
|
205
|
+
all_keys = list(base_ckpt.keys())
|
|
206
|
+
new_dict = OrderedDict()
|
|
207
|
+
for key in all_keys:
|
|
208
|
+
key_new = key
|
|
209
|
+
if 'encoder' in key:
|
|
210
|
+
key_new = key[8:]
|
|
211
|
+
# elif 'decoder' in key:
|
|
212
|
+
# continue
|
|
213
|
+
|
|
214
|
+
if ("norm1" in key) or ("attn" in key):
|
|
215
|
+
key_new = key_new.split('.')
|
|
216
|
+
key_new.insert(2, 'inv_block.Fm')
|
|
217
|
+
key_new = '.'.join(key_new)
|
|
218
|
+
elif ("norm2" in key_new) or ("mlp" in key_new):
|
|
219
|
+
key_new = key_new.split('.')
|
|
220
|
+
key_new.insert(2, 'inv_block.Gm')
|
|
221
|
+
key_new = '.'.join(key_new)
|
|
222
|
+
|
|
223
|
+
new_dict[key_new] = base_ckpt[key]
|
|
224
|
+
base_ckpt = new_dict
|
|
225
|
+
|
|
226
|
+
if hasattr(model, 'module'):
|
|
227
|
+
incompatible = model.module.load_state_dict(base_ckpt, strict=False)
|
|
228
|
+
else:
|
|
229
|
+
incompatible = model.load_state_dict(base_ckpt, strict=False)
|
|
230
|
+
|
|
231
|
+
# Compare keys manually to print mismatched keys
|
|
232
|
+
model_state_dict = model.state_dict()
|
|
233
|
+
keys_in_ckp_not_in_model = []
|
|
234
|
+
|
|
235
|
+
for key in base_ckpt.keys():
|
|
236
|
+
if key in model_state_dict.keys():
|
|
237
|
+
if base_ckpt[key].shape != model_state_dict[key].shape:
|
|
238
|
+
keys_in_ckp_not_in_model.append(key)
|
|
239
|
+
else:
|
|
240
|
+
keys_in_ckp_not_in_model.append(key)
|
|
241
|
+
# Print mismatched keys
|
|
242
|
+
if keys_in_ckp_not_in_model:
|
|
243
|
+
print("Keys in checkpoint but not in model:")
|
|
244
|
+
for key in keys_in_ckp_not_in_model:
|
|
245
|
+
print(key)
|
|
246
|
+
|
|
247
|
+
# Compare keys manually to print keys in model but not in checkpoint
|
|
248
|
+
keys_in_model_not_in_ckp = [key for key in model_state_dict.keys() if key not in base_ckpt.keys()]
|
|
249
|
+
|
|
250
|
+
# Print keys in model but not in checkpoint
|
|
251
|
+
if keys_in_model_not_in_ckp:
|
|
252
|
+
print("Keys in Model but Not in Checkpoint:")
|
|
253
|
+
for key in keys_in_model_not_in_ckp:
|
|
254
|
+
print(key)
|
|
255
|
+
else:
|
|
256
|
+
print("No keys in model but not in checkpoint.")
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
if incompatible.missing_keys:
|
|
260
|
+
logging.info('missing_keys')
|
|
261
|
+
logging.info(
|
|
262
|
+
get_missing_parameters_message(incompatible.missing_keys),
|
|
263
|
+
)
|
|
264
|
+
if incompatible.unexpected_keys:
|
|
265
|
+
logging.info('unexpected_keys')
|
|
266
|
+
logging.info(
|
|
267
|
+
get_unexpected_parameters_message(incompatible.unexpected_keys)
|
|
268
|
+
)
|
|
269
|
+
logging.info(f'Successful Loading the ckpt from {pretrained_path}')
|
|
270
|
+
|
|
271
|
+
epoch = state_dict.get('epoch', -1)
|
|
272
|
+
metrics = {}
|
|
273
|
+
for key in state_dict.keys():
|
|
274
|
+
is_metric_key = sum([item in key for item in ['metric', 'acc', 'test', 'val']]) > 0
|
|
275
|
+
if is_metric_key:
|
|
276
|
+
metrics[key] = state_dict[key]
|
|
277
|
+
logging.info(f'ckpts @ {epoch} epoch( {metrics} )')
|
|
278
|
+
return epoch, metrics
|
|
279
|
+
|
|
280
|
+
def get_missing_parameters_message(keys: List[str]) -> str:
|
|
281
|
+
"""
|
|
282
|
+
Get a logging-friendly message to report parameter names (keys) that are in
|
|
283
|
+
the model but not found in a checkpoint.
|
|
284
|
+
Args:
|
|
285
|
+
keys (list[str]): List of keys that were not found in the checkpoint.
|
|
286
|
+
Returns:
|
|
287
|
+
str: message.
|
|
288
|
+
"""
|
|
289
|
+
groups = _group_checkpoint_keys(keys)
|
|
290
|
+
msg = "Some model parameters or buffers are not found in the checkpoint:\n"
|
|
291
|
+
msg += "\n".join(
|
|
292
|
+
" " + colored(k + _group_to_str(v), "blue") for k, v in groups.items()
|
|
293
|
+
)
|
|
294
|
+
return msg
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def get_unexpected_parameters_message(keys: List[str]) -> str:
|
|
298
|
+
"""
|
|
299
|
+
Get a logging-friendly message to report parameter names (keys) that are in
|
|
300
|
+
the checkpoint but not found in the model.
|
|
301
|
+
Args:
|
|
302
|
+
keys (list[str]): List of keys that were not found in the model.
|
|
303
|
+
Returns:
|
|
304
|
+
str: message.
|
|
305
|
+
"""
|
|
306
|
+
groups = _group_checkpoint_keys(keys)
|
|
307
|
+
msg = "The checkpoint state_dict contains keys that are not used by the model:\n"
|
|
308
|
+
msg += "\n".join(
|
|
309
|
+
" " + colored(k + _group_to_str(v), "magenta") for k, v in groups.items()
|
|
310
|
+
)
|
|
311
|
+
return msg
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
def _strip_prefix_if_present(state_dict: Dict[str, Any], prefix: str) -> None:
|
|
315
|
+
"""
|
|
316
|
+
Strip the prefix in metadata, if any.
|
|
317
|
+
Args:
|
|
318
|
+
state_dict (OrderedDict): a state-dict to be loaded to the model.
|
|
319
|
+
prefix (str): prefix.
|
|
320
|
+
"""
|
|
321
|
+
keys = sorted(state_dict.keys())
|
|
322
|
+
if not all(len(key) == 0 or key.startswith(prefix) for key in keys):
|
|
323
|
+
return
|
|
324
|
+
|
|
325
|
+
for key in keys:
|
|
326
|
+
newkey = key[len(prefix):]
|
|
327
|
+
state_dict[newkey] = state_dict.pop(key)
|
|
328
|
+
|
|
329
|
+
# also strip the prefix in metadata, if any..
|
|
330
|
+
try:
|
|
331
|
+
metadata = state_dict._metadata # pyre-ignore
|
|
332
|
+
except AttributeError:
|
|
333
|
+
pass
|
|
334
|
+
else:
|
|
335
|
+
for key in list(metadata.keys()):
|
|
336
|
+
# for the metadata dict, the key can be:
|
|
337
|
+
# '': for the DDP module, which we want to remove.
|
|
338
|
+
# 'module': for the actual model.
|
|
339
|
+
# 'module.xx.xx': for the rest.
|
|
340
|
+
|
|
341
|
+
if len(key) == 0:
|
|
342
|
+
continue
|
|
343
|
+
newkey = key[len(prefix):]
|
|
344
|
+
metadata[newkey] = metadata.pop(key)
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def _group_checkpoint_keys(keys: List[str]) -> Dict[str, List[str]]:
|
|
348
|
+
"""
|
|
349
|
+
Group keys based on common prefixes. A prefix is the string up to the final
|
|
350
|
+
"." in each key.
|
|
351
|
+
Args:
|
|
352
|
+
keys (list[str]): list of parameter names, i.e. keys in the model
|
|
353
|
+
checkpoint dict.
|
|
354
|
+
Returns:
|
|
355
|
+
dict[list]: keys with common prefixes are grouped into lists.
|
|
356
|
+
"""
|
|
357
|
+
groups = defaultdict(list)
|
|
358
|
+
for key in keys:
|
|
359
|
+
pos = key.rfind(".")
|
|
360
|
+
if pos >= 0:
|
|
361
|
+
head, tail = key[:pos], [key[pos + 1:]]
|
|
362
|
+
else:
|
|
363
|
+
head, tail = key, []
|
|
364
|
+
groups[head].extend(tail)
|
|
365
|
+
return groups
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def _group_to_str(group: List[str]) -> str:
|
|
369
|
+
"""
|
|
370
|
+
Format a group of parameter name suffixes into a loggable string.
|
|
371
|
+
Args:
|
|
372
|
+
group (list[str]): list of parameter name suffixes.
|
|
373
|
+
Returns:
|
|
374
|
+
str: formated string.
|
|
375
|
+
"""
|
|
376
|
+
if len(group) == 0:
|
|
377
|
+
return ""
|
|
378
|
+
|
|
379
|
+
if len(group) == 1:
|
|
380
|
+
return "." + group[0]
|
|
381
|
+
|
|
382
|
+
return ".{" + ", ".join(group) + "}"
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def _named_modules_with_dup(
|
|
386
|
+
model: nn.Module, prefix: str = ""
|
|
387
|
+
) -> Iterable[Tuple[str, nn.Module]]:
|
|
388
|
+
"""
|
|
389
|
+
The same as `model.named_modules()`, except that it includes
|
|
390
|
+
duplicated modules that have more than one name.
|
|
391
|
+
"""
|
|
392
|
+
yield prefix, model
|
|
393
|
+
for name, module in model._modules.items(): # pyre-ignore
|
|
394
|
+
if module is None:
|
|
395
|
+
continue
|
|
396
|
+
submodule_prefix = prefix + ("." if prefix else "") + name
|
|
397
|
+
yield from _named_modules_with_dup(module, submodule_prefix)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
def bert2vit_ckpt_rename(state_dict,layerCount=8):
|
|
401
|
+
out_Order_dict=OrderedDict({})
|
|
402
|
+
for layer in range(0, layerCount):
|
|
403
|
+
#collect qkv
|
|
404
|
+
bert_q_weight_key="bert.encoder.layer." + str(layer) +".attention.self.query.weight"
|
|
405
|
+
bert_q_bias_key="bert.encoder.layer." + str(layer) +".attention.self.query.bias"
|
|
406
|
+
bert_k_weight_key="bert.encoder.layer." + str(layer) +".attention.self.key.weight"
|
|
407
|
+
bert_k_bias_key="bert.encoder.layer." + str(layer) +".attention.self.key.bias"
|
|
408
|
+
bert_v_weight_key="bert.encoder.layer." + str(layer) +".attention.self.value.weight"
|
|
409
|
+
bert_v_bias_key="bert.encoder.layer." + str(layer) +".attention.self.value.bias"
|
|
410
|
+
pvit_weight_key="blocks." + str(layer) +".attn.qkv.weight"
|
|
411
|
+
pvit_bias_key="blocks." + str(layer) +".attn.qkv.bias"
|
|
412
|
+
mergedQKV_weight= torch.cat((state_dict[bert_q_weight_key],state_dict[bert_k_weight_key],state_dict[bert_v_weight_key]), 0)
|
|
413
|
+
mergedQKV_bias= torch.cat((state_dict[bert_q_bias_key],state_dict[bert_k_bias_key],state_dict[bert_v_bias_key]), 0)
|
|
414
|
+
out_Order_dict[pvit_weight_key]=mergedQKV_weight
|
|
415
|
+
out_Order_dict[pvit_bias_key]=mergedQKV_bias
|
|
416
|
+
#rename other layers
|
|
417
|
+
for key in state_dict.keys():
|
|
418
|
+
if "attention.output.dense" in key:
|
|
419
|
+
newKey=key.replace("attention.output.dense","attn.proj" )
|
|
420
|
+
newKey=newKey.replace("bert.encoder.layer","blocks" )
|
|
421
|
+
out_Order_dict[newKey]=state_dict[key]
|
|
422
|
+
elif "attention.output.LayerNorm" in key:
|
|
423
|
+
newKey=key.replace("attention.output.LayerNorm","norm1" )
|
|
424
|
+
newKey=newKey.replace("bert.encoder.layer","blocks" )
|
|
425
|
+
out_Order_dict[newKey]=state_dict[key]
|
|
426
|
+
elif "intermediate.dense" in key:
|
|
427
|
+
newKey=key.replace("intermediate.dense","mlp.fc1" )
|
|
428
|
+
newKey=newKey.replace("bert.encoder.layer","blocks" )
|
|
429
|
+
out_Order_dict[newKey]=state_dict[key]
|
|
430
|
+
elif "output.dense" in key and "attention" not in key:
|
|
431
|
+
newKey=key.replace("output.dense","mlp.fc2" )
|
|
432
|
+
newKey=newKey.replace("bert.encoder.layer","blocks" )
|
|
433
|
+
out_Order_dict[newKey]=state_dict[key]
|
|
434
|
+
elif "output.LayerNorm" in key:
|
|
435
|
+
newKey=key.replace("output.LayerNorm","norm2" )
|
|
436
|
+
newKey=newKey.replace("bert.encoder.layer","blocks" )
|
|
437
|
+
out_Order_dict[newKey]=state_dict[key]
|
|
438
|
+
return out_Order_dict
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import hashlib
|
|
2
|
+
import json
|
|
3
|
+
import os
|
|
4
|
+
from ast import literal_eval
|
|
5
|
+
from typing import Any, Dict, List, Tuple, Union
|
|
6
|
+
from multimethod import multimethod
|
|
7
|
+
import yaml
|
|
8
|
+
import logging
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def print_args(args, printer=logging.info):
|
|
12
|
+
printer("========== args =============")
|
|
13
|
+
for arg, content in args.__dict__.items():
|
|
14
|
+
printer("{}:{}".format(arg, content))
|
|
15
|
+
printer("========== args END =============")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class EasyConfig(dict):
|
|
19
|
+
def __getattr__(self, key: str) -> Any:
|
|
20
|
+
if key not in self:
|
|
21
|
+
raise AttributeError(key)
|
|
22
|
+
return self[key]
|
|
23
|
+
|
|
24
|
+
def __setattr__(self, key: str, value: Any) -> None:
|
|
25
|
+
self[key] = value
|
|
26
|
+
|
|
27
|
+
def __delattr__(self, key: str) -> None:
|
|
28
|
+
del self[key]
|
|
29
|
+
|
|
30
|
+
def load(self, fpath: str, *, recursive: bool = False) -> None:
|
|
31
|
+
"""load cfg from yaml
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
fpath (str): path to the yaml file
|
|
35
|
+
recursive (bool, optional): recursily load its parent defaul yaml files. Defaults to False.
|
|
36
|
+
"""
|
|
37
|
+
if not os.path.exists(fpath):
|
|
38
|
+
raise FileNotFoundError(fpath)
|
|
39
|
+
fpaths = [fpath]
|
|
40
|
+
if recursive:
|
|
41
|
+
extension = os.path.splitext(fpath)[1]
|
|
42
|
+
while os.path.dirname(fpath) != fpath:
|
|
43
|
+
fpath = os.path.dirname(fpath)
|
|
44
|
+
fpaths.append(os.path.join(fpath, 'default' + extension))
|
|
45
|
+
for fpath in reversed(fpaths):
|
|
46
|
+
if os.path.exists(fpath):
|
|
47
|
+
with open(fpath) as f:
|
|
48
|
+
self.update(yaml.safe_load(f))
|
|
49
|
+
|
|
50
|
+
def reload(self, fpath: str, *, recursive: bool = False) -> None:
|
|
51
|
+
self.clear()
|
|
52
|
+
self.load(fpath, recursive=recursive)
|
|
53
|
+
|
|
54
|
+
# mutimethod makes python supports function overloading
|
|
55
|
+
@multimethod
|
|
56
|
+
def update(self, other: Dict) -> None:
|
|
57
|
+
for key, value in other.items():
|
|
58
|
+
if isinstance(value, dict):
|
|
59
|
+
if key not in self or not isinstance(self[key], EasyConfig):
|
|
60
|
+
self[key] = EasyConfig()
|
|
61
|
+
# recursively update
|
|
62
|
+
self[key].update(value)
|
|
63
|
+
else:
|
|
64
|
+
self[key] = value
|
|
65
|
+
|
|
66
|
+
@multimethod
|
|
67
|
+
def update(self, opts: Union[List, Tuple]) -> None:
|
|
68
|
+
index = 0
|
|
69
|
+
while index < len(opts):
|
|
70
|
+
opt = opts[index]
|
|
71
|
+
if opt.startswith('--'):
|
|
72
|
+
opt = opt[2:]
|
|
73
|
+
if '=' in opt:
|
|
74
|
+
key, value = opt.split('=', 1)
|
|
75
|
+
index += 1
|
|
76
|
+
else:
|
|
77
|
+
key, value = opt, opts[index + 1]
|
|
78
|
+
index += 2
|
|
79
|
+
current = self
|
|
80
|
+
subkeys = key.split('.')
|
|
81
|
+
try:
|
|
82
|
+
value = literal_eval(value)
|
|
83
|
+
except:
|
|
84
|
+
pass
|
|
85
|
+
for subkey in subkeys[:-1]:
|
|
86
|
+
current = current.setdefault(subkey, EasyConfig())
|
|
87
|
+
current[subkeys[-1]] = value
|
|
88
|
+
|
|
89
|
+
def dict(self) -> Dict[str, Any]:
|
|
90
|
+
configs = dict()
|
|
91
|
+
for key, value in self.items():
|
|
92
|
+
if isinstance(value, EasyConfig):
|
|
93
|
+
value = value.dict()
|
|
94
|
+
configs[key] = value
|
|
95
|
+
return configs
|
|
96
|
+
|
|
97
|
+
def hash(self) -> str:
|
|
98
|
+
buffer = json.dumps(self.dict(), sort_keys=True)
|
|
99
|
+
return hashlib.sha256(buffer.encode()).hexdigest()
|
|
100
|
+
|
|
101
|
+
def __str__(self) -> str:
|
|
102
|
+
texts = []
|
|
103
|
+
for key, value in self.items():
|
|
104
|
+
if isinstance(value, EasyConfig):
|
|
105
|
+
seperator = '\n'
|
|
106
|
+
else:
|
|
107
|
+
seperator = ' '
|
|
108
|
+
text = key + ':' + seperator + str(value)
|
|
109
|
+
lines = text.split('\n')
|
|
110
|
+
for k, line in enumerate(lines[1:]):
|
|
111
|
+
lines[k + 1] = (' ' * 2) + line
|
|
112
|
+
texts.extend(lines)
|
|
113
|
+
return '\n'.join(texts)
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import torch
|
|
3
|
+
from torch import distributed as dist
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _init_dist_pytorch(backend, **kwargs):
|
|
7
|
+
rank = int(os.environ['RANK'])
|
|
8
|
+
num_gpus = torch.cuda.device_count()
|
|
9
|
+
torch.cuda.set_device(rank % num_gpus)
|
|
10
|
+
dist.init_process_group(backend=backend, **kwargs)
|
|
11
|
+
print(f'init distributed in rank {torch.distributed.get_rank()}')
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_dist_info(cfg):
|
|
15
|
+
mp = False
|
|
16
|
+
if dist.is_available() and dist.is_initialized():
|
|
17
|
+
rank = dist.get_rank()
|
|
18
|
+
world_size = dist.get_world_size()
|
|
19
|
+
cfg.launcher = 'pytorch'
|
|
20
|
+
else:
|
|
21
|
+
# only supports 1 node for now
|
|
22
|
+
rank = cfg.local_rank
|
|
23
|
+
world_size = torch.cuda.device_count()
|
|
24
|
+
mp = cfg.launcher in ['mp', 'multiprocessing'] and world_size > 1
|
|
25
|
+
distributed = world_size > 1
|
|
26
|
+
print(f'launch {cfg.launcher} with {world_size} GPUs, current rank: {rank}')
|
|
27
|
+
return rank, world_size, distributed, mp
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def reduce_tensor(tensor):
|
|
31
|
+
'''
|
|
32
|
+
for acc kind, get the mean in each gpu
|
|
33
|
+
'''
|
|
34
|
+
rt = tensor.clone()
|
|
35
|
+
dist.all_reduce(rt, op=dist.ReduceOp.SUM)
|
|
36
|
+
rt /= dist.get_world_size()
|
|
37
|
+
return rt
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def gather_tensor(tensor):
|
|
41
|
+
output_tensors = [tensor.clone() for _ in range(dist.get_world_size())]
|
|
42
|
+
dist.all_gather(output_tensors, tensor)
|
|
43
|
+
concat = torch.cat(output_tensors, dim=0)
|
|
44
|
+
return concat
|
|
45
|
+
|
|
46
|
+
def find_free_port():
|
|
47
|
+
import socket
|
|
48
|
+
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
49
|
+
# Binding to port 0 will cause the OS to find an available port for us
|
|
50
|
+
sock.bind(("", 0))
|
|
51
|
+
port = sock.getsockname()[1]
|
|
52
|
+
sock.close()
|
|
53
|
+
# NOTE: there is still a chance the port could be taken by other processes.
|
|
54
|
+
return port
|