Kohya_ss_2 / sd-scripts /library /accelerator_setup.py
ChBysk's picture
Upload folder using huggingface_hub (part 2)
622d48e verified
Raw
History Blame Contribute Delete
7.38 kB
"""Accelerator / dtype / dataset-args setup helpers.
Hosts the routines that prepare the Accelerator (incl. DeepSpeed plugin and
DDP options), resolve mixed-precision dtypes, normalise dataset-related
arguments, patch the fp16 grad scaler, and toggle the ``HIGH_VRAM`` mode flag.
``HIGH_VRAM`` is a mutable module-level flag toggled by ``enable_high_vram``
and read from ``library.caching`` / ``library.dataset`` / the strategy
modules. Extracted from ``library.train_util`` and re-exported there for
backward compatibility (the legacy ``train_util.HIGH_VRAM`` attribute is
served via a module-level ``__getattr__`` shim).
"""
import argparse
import datetime
import logging
import os
import torch
from accelerate import Accelerator, DistributedDataParallelKwargs, InitProcessGroupKwargs
from packaging.version import Version
import library.deepspeed_utils as deepspeed_utils
from library.utils import setup_logging
setup_logging()
logger = logging.getLogger(__name__)
# Mutable module-level flag toggled by enable_high_vram(). Read from caching /
# dataset / strategy modules to skip per-step CUDA cache clears on big-VRAM rigs.
HIGH_VRAM = False
def enable_high_vram(args: argparse.Namespace):
if args.highvram:
logger.info("highvram is enabled / highvramが有効です")
global HIGH_VRAM
HIGH_VRAM = True
def prepare_dataset_args(args: argparse.Namespace, support_metadata: bool):
# backward compatibility
if args.caption_extention is not None:
args.caption_extension = args.caption_extention
args.caption_extention = None
# assert args.resolution is not None, f"resolution is required / resolution(解像度)を指定してください"
if args.resolution is not None:
args.resolution = tuple([int(r) for r in args.resolution.split(",")])
if len(args.resolution) == 1:
args.resolution = (args.resolution[0], args.resolution[0])
assert (
len(args.resolution) == 2
), f"resolution must be 'size' or 'width,height' / resolution(解像度)は'サイズ'または'幅','高さ'で指定してください: {args.resolution}"
if args.skip_image_resolution is not None:
args.skip_image_resolution = tuple([int(r) for r in args.skip_image_resolution.split(",")])
if len(args.skip_image_resolution) == 1:
args.skip_image_resolution = (args.skip_image_resolution[0], args.skip_image_resolution[0])
assert (
len(args.skip_image_resolution) == 2
), f"skip_image_resolution must be 'size' or 'width,height' / skip_image_resolutionは'サイズ'または'幅','高さ'で指定してください: {args.skip_image_resolution}"
if args.face_crop_aug_range is not None:
args.face_crop_aug_range = tuple([float(r) for r in args.face_crop_aug_range.split(",")])
assert (
len(args.face_crop_aug_range) == 2 and args.face_crop_aug_range[0] <= args.face_crop_aug_range[1]
), f"face_crop_aug_range must be two floats / face_crop_aug_rangeは'下限,上限'で指定してください: {args.face_crop_aug_range}"
else:
args.face_crop_aug_range = None
if support_metadata:
if args.in_json is not None and (args.color_aug or args.random_crop):
logger.warning(
f"latents in npz is ignored when color_aug or random_crop is True / color_augまたはrandom_cropを有効にした場合、npzファイルのlatentsは無視されます"
)
def prepare_accelerator(args: argparse.Namespace):
"""
this function also prepares deepspeed plugin
"""
import time
if args.logging_dir is None:
logging_dir = None
else:
log_prefix = "" if args.log_prefix is None else args.log_prefix
logging_dir = args.logging_dir + "/" + log_prefix + time.strftime("%Y%m%d%H%M%S", time.localtime())
if args.log_with is None:
if logging_dir is not None:
log_with = "tensorboard"
else:
log_with = None
else:
log_with = args.log_with
if log_with in ["tensorboard", "all"]:
if logging_dir is None:
raise ValueError(
"logging_dir is required when log_with is tensorboard / Tensorboardを使う場合、logging_dirを指定してください"
)
if log_with in ["wandb", "all"]:
try:
import wandb
except ImportError:
raise ImportError("No wandb / wandb がインストールされていないようです")
if logging_dir is not None:
os.makedirs(logging_dir, exist_ok=True)
os.environ["WANDB_DIR"] = logging_dir
if args.wandb_api_key is not None:
wandb.login(key=args.wandb_api_key)
# torch.compile のオプション。 NO の場合は torch.compile は使わない
dynamo_backend = "NO"
if args.torch_compile:
dynamo_backend = args.dynamo_backend
kwargs_handlers = [
(
InitProcessGroupKwargs(
backend="gloo" if os.name == "nt" or not torch.cuda.is_available() else "nccl",
init_method=(
"env://?use_libuv=False" if os.name == "nt" and Version(torch.__version__) >= Version("2.4.0") else None
),
timeout=datetime.timedelta(minutes=args.ddp_timeout) if args.ddp_timeout else None,
)
if torch.cuda.device_count() > 1
else None
),
(
DistributedDataParallelKwargs(
gradient_as_bucket_view=args.ddp_gradient_as_bucket_view, static_graph=args.ddp_static_graph
)
if args.ddp_gradient_as_bucket_view or args.ddp_static_graph
else None
),
]
kwargs_handlers = [i for i in kwargs_handlers if i is not None]
deepspeed_plugin = deepspeed_utils.prepare_deepspeed_plugin(args)
accelerator = Accelerator(
gradient_accumulation_steps=args.gradient_accumulation_steps,
mixed_precision=args.mixed_precision,
log_with=log_with,
project_dir=logging_dir,
kwargs_handlers=kwargs_handlers,
dynamo_backend=dynamo_backend,
deepspeed_plugin=deepspeed_plugin,
)
print("accelerator device:", accelerator.device)
return accelerator
def prepare_dtype(args: argparse.Namespace):
weight_dtype = torch.float32
if args.mixed_precision == "fp16":
weight_dtype = torch.float16
elif args.mixed_precision == "bf16":
weight_dtype = torch.bfloat16
save_dtype = None
if args.save_precision == "fp16":
save_dtype = torch.float16
elif args.save_precision == "bf16":
save_dtype = torch.bfloat16
elif args.save_precision == "float":
save_dtype = torch.float32
return weight_dtype, save_dtype
def patch_accelerator_for_fp16_training(accelerator):
from accelerate import DistributedType
if accelerator.distributed_type == DistributedType.DEEPSPEED:
return
org_unscale_grads = accelerator.scaler._unscale_grads_
def _unscale_grads_replacer(optimizer, inv_scale, found_inf, allow_fp16):
return org_unscale_grads(optimizer, inv_scale, found_inf, True)
accelerator.scaler._unscale_grads_ = _unscale_grads_replacer