Text-to-3D
image-to-3d
code / SparseNeuS_demo_v1 /utils /training_utils.py
Chao Xu
sparseneus and elev est
854f0d0
raw
history blame
3.77 kB
import numpy as np
import torchvision.utils as vutils
import torch, random
import torch.nn.functional as F
# print arguments
def print_args(args):
print("################################ args ################################")
for k, v in args.__dict__.items():
print("{0: <10}\t{1: <30}\t{2: <20}".format(k, str(v), str(type(v))))
print("########################################################################")
# torch.no_grad warpper for functions
def make_nograd_func(func):
def wrapper(*f_args, **f_kwargs):
with torch.no_grad():
ret = func(*f_args, **f_kwargs)
return ret
return wrapper
# convert a function into recursive style to handle nested dict/list/tuple variables
def make_recursive_func(func):
def wrapper(vars, device=None):
if isinstance(vars, list):
return [wrapper(x, device) for x in vars]
elif isinstance(vars, tuple):
return tuple([wrapper(x, device) for x in vars])
elif isinstance(vars, dict):
return {k: wrapper(v, device) for k, v in vars.items()}
else:
return func(vars, device)
return wrapper
@make_recursive_func
def tensor2float(vars):
if isinstance(vars, float):
return vars
elif isinstance(vars, torch.Tensor):
return vars.data.item()
else:
raise NotImplementedError("invalid input type {} for tensor2float".format(type(vars)))
@make_recursive_func
def tensor2numpy(vars):
if isinstance(vars, np.ndarray):
return vars
elif isinstance(vars, torch.Tensor):
return vars.detach().cpu().numpy().copy()
else:
raise NotImplementedError("invalid input type {} for tensor2numpy".format(type(vars)))
@make_recursive_func
def numpy2tensor(vars, device='cpu'):
if not isinstance(vars, torch.Tensor) and vars is not None :
return torch.tensor(vars, device=device)
elif isinstance(vars, torch.Tensor):
return vars
elif vars is None:
return vars
else:
raise NotImplementedError("invalid input type {} for float2tensor".format(type(vars)))
@make_recursive_func
def tocuda(vars, device='cuda'):
if isinstance(vars, torch.Tensor):
return vars.to(device)
elif isinstance(vars, str):
return vars
else:
raise NotImplementedError("invalid input type {} for tocuda".format(type(vars)))
import torch.distributed as dist
def synchronize():
"""
Helper function to synchronize (barrier) among all processes when
using distributed training
"""
if not dist.is_available():
return
if not dist.is_initialized():
return
world_size = dist.get_world_size()
if world_size == 1:
return
dist.barrier()
def get_world_size():
if not dist.is_available():
return 1
if not dist.is_initialized():
return 1
return dist.get_world_size()
def reduce_scalar_outputs(scalar_outputs):
world_size = get_world_size()
if world_size < 2:
return scalar_outputs
with torch.no_grad():
names = []
scalars = []
for k in sorted(scalar_outputs.keys()):
names.append(k)
if isinstance(scalar_outputs[k], torch.Tensor):
scalars.append(scalar_outputs[k])
else:
scalars.append(torch.tensor(scalar_outputs[k], device='cuda'))
scalars = torch.stack(scalars, dim=0)
dist.reduce(scalars, dst=0)
if dist.get_rank() == 0:
# only main process gets accumulated, so only divide by
# world_size in this case
scalars /= world_size
reduced_scalars = {k: v for k, v in zip(names, scalars)}
return reduced_scalars