

# Copyright 2021 The HuggingFace Team. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pathlib import Path

import torch

from ...utils import is_npu_available, is_xpu_available
from .config_args import ClusterConfig, default_json_config_file
from .config_utils import SubcommandHelpFormatter


__A			:					List[Any]						=			'Create a default config file for Accelerate with only a few flags set.'





def 	__a     (      A__			:  Optional[Any]="no"			,  A__			:  str = default_json_config_file			,  A__			:  bool = False       ):
    SCREAMING_SNAKE_CASE										=   Path(lowerCAmelCase__       )
    path.parent.mkdir(parents=lowerCAmelCase__			,  exist_ok=lowerCAmelCase__       )
    if path.exists():
        print(
            F"Configuration already exists at {save_location}, will not override. Run `accelerate config` manually or pass a different `save_location`."       )
        return False
    SCREAMING_SNAKE_CASE										=   mixed_precision.lower()
    if mixed_precision not in ["no", "fp16", "bf16", "fp8"]:
        raise ValueError(
            F"`mixed_precision` should be one of \'no\', \'fp16\', \'bf16\', or \'fp8\'. Received {mixed_precision}"       )
    SCREAMING_SNAKE_CASE										=   {
        "compute_environment": "LOCAL_MACHINE",
        "mixed_precision": mixed_precision,
    }
    if torch.cuda.is_available():
        SCREAMING_SNAKE_CASE										=   torch.cuda.device_count()
        SCREAMING_SNAKE_CASE										=   num_gpus
        SCREAMING_SNAKE_CASE										=   False
        if num_gpus > 1:
            SCREAMING_SNAKE_CASE										=   "MULTI_GPU"
        else:
            SCREAMING_SNAKE_CASE										=   "NO"
    elif is_xpu_available() and use_xpu:
        SCREAMING_SNAKE_CASE										=   torch.xpu.device_count()
        SCREAMING_SNAKE_CASE										=   num_xpus
        SCREAMING_SNAKE_CASE										=   False
        if num_xpus > 1:
            SCREAMING_SNAKE_CASE										=   "MULTI_XPU"
        else:
            SCREAMING_SNAKE_CASE										=   "NO"
    elif is_npu_available():
        SCREAMING_SNAKE_CASE										=   torch.npu.device_count()
        SCREAMING_SNAKE_CASE										=   num_npus
        SCREAMING_SNAKE_CASE										=   False
        if num_npus > 1:
            SCREAMING_SNAKE_CASE										=   "MULTI_NPU"
        else:
            SCREAMING_SNAKE_CASE										=   "NO"
    else:
        SCREAMING_SNAKE_CASE										=   0
        SCREAMING_SNAKE_CASE										=   True
        SCREAMING_SNAKE_CASE										=   1
        SCREAMING_SNAKE_CASE										=   "NO"
    SCREAMING_SNAKE_CASE										=   ClusterConfig(**lowerCAmelCase__       )
    config.to_json_file(lowerCAmelCase__       )
    return path





def 	__a     (      A__			:  Optional[Any]			,  A__			:  Optional[int]       ):
    SCREAMING_SNAKE_CASE										=   parser.add_parser("default"			,  parents=lowerCAmelCase__			,  help=lowerCAmelCase__			,  formatter_class=lowerCAmelCase__       )
    parser.add_argument(
        "--config_file"			,  default=lowerCAmelCase__			,  help=(
            "The path to use to store the config file. Will default to a file named default_config.yaml in the cache "
            "location, which is the content of the environment `HF_HOME` suffixed with \'accelerate\', or if you don\'t have "
            "such an environment variable, your cache directory (\'~/.cache\' or the content of `XDG_CACHE_HOME`) suffixed "
            "with \'huggingface\'."
        )			,  dest="save_location"			,  )

    parser.add_argument(
        "--mixed_precision"			,  choices=["no", "fp16", "bf16"]			,  type=lowerCAmelCase__			,  help="Whether or not to use mixed precision training. "
        "Choose between FP16 and BF16 (bfloat16) training. "
        "BF16 training is only supported on Nvidia Ampere GPUs and PyTorch 1.10 or later."			,  default="no"			,  )
    parser.set_defaults(func=lowerCAmelCase__       )
    return parser





def 	__a     (      A__			:  Optional[int]       ):
    SCREAMING_SNAKE_CASE										=   write_basic_config(args.mixed_precision			,  args.save_location       )
    if config_file:
        print(F"accelerate configuration saved at {config_file}"       )




import logging
import os
import threading
import time


try:
				import warnings
except ImportError:
				__snake_case     :Any			       =None

try:
				import msvcrt
except ImportError:
				__snake_case     :Union[str, Any]			       =None

try:
				import fcntl
except ImportError:
				__snake_case     :str			       =None


# Backward compatibility
# ------------------------------------------------
try:
				TimeoutError
except NameError:
				__snake_case     :str			       =OSError


# Data
# ------------------------------------------------
__snake_case     :Any			       =[
    'Timeout',
    'BaseFileLock',
    'WindowsFileLock',
    'UnixFileLock',
    'SoftFileLock',
    'FileLock',
]

__snake_case     :str			       ='3.0.12'


__snake_case     :str			       =None






def  lowerCamelCase_	(      )       ->							List[str]:

							'''simple docstring'''






							global _logger
							A      						=    _logger or logging.getLogger(__name__				)
							return _logger



class        lowerCAmelCase__					(  _lowerCamelCase       ):


				def __init__(							self      :  Tuple						, __UpperCamelCase      :  Union[str, Any]       )		->     List[Any]:
											A      						=    lock_file
											return None


				def __str__(							self      :  List[Any]       )		->     int:
											A      						=    f'''The file lock \'{self.lock_file}\' could not be acquired.'''
											return temp





class        lowerCAmelCase__					:


				def __init__(							self      :  int						, __UpperCamelCase      :  Union[str, Any]       )		->     List[str]:
											A      						=    lock
											return None


				def __enter__(							self      :  Dict       )		->     Dict:
											return self.lock


				def __exit__(							self      :  int						, __UpperCamelCase      :  str						, __UpperCamelCase      :  Optional[int]						, __UpperCamelCase      :  Any       )		->     Optional[int]:
											self.lock.release()
											return None





class        lowerCAmelCase__					:


				def __init__(							self      :  List[Any]						, __UpperCamelCase      :  List[str]						, __UpperCamelCase      :  List[Any]=-1						, __UpperCamelCase      :  Optional[Any]=None       )		->     Dict:
											A      						=    max_filename_length if max_filename_length is not None else 255
											# Hash the filename if it's too long
											A      						=    self.hash_filename_if_too_long(__UpperCamelCase						, __UpperCamelCase       )
											# The path to the lock file.
											A      						=    lock_file

											# The file descriptor for the *_lock_file* as it is returned by the
											# os.open() function.
											# This file lock is only NOT None, if the object currently holds the
											# lock.
											A      						=    None

											# The default timeout value.
											A      						=    timeout

											# We use this lock primarily for the lock counter.
											A      						=    threading.Lock()

											# The lock counter is used for implementing the nested locking
											# mechanism. Whenever the lock is acquired, the counter is increased and
											# the lock is only released, when this value is 0 again.
											A      						=    0
											return None


				@property
				def __UpperCamelCase						(							self      :  str       )		->     Union[str, Any]:
											return self._lock_file


				@property
				def __UpperCamelCase						(							self      :  Tuple       )		->     Union[str, Any]:
											return self._timeout


				@timeout.setter
				def __UpperCamelCase						(							self      :  Union[str, Any]						, __UpperCamelCase      :  Any       )		->     Tuple:
											A      						=    float(__UpperCamelCase       )
											return None


				def __UpperCamelCase						(							self      :  Optional[Any]       )		->     Any:
											raise NotImplementedError()


				def __UpperCamelCase						(							self      :  int       )		->     str:
											raise NotImplementedError()


				@property
				def __UpperCamelCase						(							self      :  List[Any]       )		->     Optional[Any]:
											return self._lock_file_fd is not None


				def __UpperCamelCase						(							self      :  int						, __UpperCamelCase      :  List[str]=None						, __UpperCamelCase      :  Any=0.0_5       )		->     Any:
											# Use the default timeout, if no timeout is provided.
											if timeout is None:
																		A      						=    self.timeout

											# Increment the number right at the beginning.
											# We can still undo it, if something fails.
											with self._thread_lock:
																		self._lock_counter += 1

											A      						=    id(self       )
											A      						=    self._lock_file
											A      						=    time.time()
											try:
																		while True:
																									with self._thread_lock:
																																if not self.is_locked:
																																							logger().debug(f'''Attempting to acquire lock {lock_id} on {lock_filename}'''       )
																																							self._acquire()

																									if self.is_locked:
																																logger().debug(f'''Lock {lock_id} acquired on {lock_filename}'''       )
																																break
																									elif timeout >= 0 and time.time() - start_time > timeout:
																																logger().debug(f'''Timeout on acquiring lock {lock_id} on {lock_filename}'''       )
																																raise Timeout(self._lock_file       )
																									else:
																																logger().debug(
																																    f'''Lock {lock_id} not acquired on {lock_filename}, waiting {poll_intervall} seconds ...'''       )
																																time.sleep(__UpperCamelCase       )
											except:  # noqa
																		# Something did go wrong, so decrement the counter.
																		with self._thread_lock:
																									A      						=    max(0						, self._lock_counter - 1       )

																		raise
											return _Acquire_ReturnProxy(lock=self       )


				def __UpperCamelCase						(							self      :  Optional[int]						, __UpperCamelCase      :  Tuple=False       )		->     Tuple:
											with self._thread_lock:
																		if self.is_locked:
																									self._lock_counter -= 1

																									if self._lock_counter == 0 or force:
																																A      						=    id(self       )
																																A      						=    self._lock_file

																																logger().debug(f'''Attempting to release lock {lock_id} on {lock_filename}'''       )
																																self._release()
																																A      						=    0
																																logger().debug(f'''Lock {lock_id} released on {lock_filename}'''       )

											return None


				def __enter__(							self      :  int       )		->     Dict:
											self.acquire()
											return self


				def __exit__(							self      :  List[str]						, __UpperCamelCase      :  Dict						, __UpperCamelCase      :  Optional[Any]						, __UpperCamelCase      :  str       )		->     Dict:
											self.release()
											return None


				def __del__(							self      :  Union[str, Any]       )		->     Optional[int]:
											self.release(force=__UpperCamelCase       )
											return None


				def __UpperCamelCase						(							self      :  Union[str, Any]						, __UpperCamelCase      :  str						, __UpperCamelCase      :  int       )		->     str:
											A      						=    os.path.basename(__UpperCamelCase       )
											if len(__UpperCamelCase       ) > max_length and max_length > 0:
																		A      						=    os.path.dirname(__UpperCamelCase       )
																		A      						=    str(hash(__UpperCamelCase       )       )
																		A      						=    filename[: max_length - len(__UpperCamelCase       ) - 8] + '...' + hashed_filename + '.lock'
																		return os.path.join(__UpperCamelCase						, __UpperCamelCase       )
											else:
																		return path





class        lowerCAmelCase__					(  _lowerCamelCase       ):


				def __init__(							self      :  Tuple						, __UpperCamelCase      :  List[str]						, __UpperCamelCase      :  Tuple=-1						, __UpperCamelCase      :  Optional[Any]=None       )		->     Union[str, Any]:
											from .file_utils import relative_to_absolute_path

											super().__init__(__UpperCamelCase						, timeout=__UpperCamelCase						, max_filename_length=__UpperCamelCase       )
											A      						=    '\\\\?\\' + relative_to_absolute_path(self.lock_file       )


				def __UpperCamelCase						(							self      :  Any       )		->     Any:
											A      						=    os.O_RDWR | os.O_CREAT | os.O_TRUNC

											try:
																		A      						=    os.open(self._lock_file						, __UpperCamelCase       )
											except OSError:
																		pass
											else:
																		try:
																									msvcrt.locking(__UpperCamelCase						, msvcrt.LK_NBLCK						, 1       )
																		except OSError:
																									os.close(__UpperCamelCase       )
																		else:
																									A      						=    fd
											return None


				def __UpperCamelCase						(							self      :  Optional[Any]       )		->     List[Any]:
											A      						=    self._lock_file_fd
											A      						=    None
											msvcrt.locking(__UpperCamelCase						, msvcrt.LK_UNLCK						, 1       )
											os.close(__UpperCamelCase       )

											try:
																		os.remove(self._lock_file       )
											# Probably another instance of the application
											# that acquired the file lock.
											except OSError:
																		pass
											return None





class        lowerCAmelCase__					(  _lowerCamelCase       ):


				def __init__(							self      :  List[Any]						, __UpperCamelCase      :  Any						, __UpperCamelCase      :  List[Any]=-1						, __UpperCamelCase      :  Dict=None       )		->     Dict:
											A      						=    os.statvfs(os.path.dirname(__UpperCamelCase       )       ).f_namemax
											super().__init__(__UpperCamelCase						, timeout=__UpperCamelCase						, max_filename_length=__UpperCamelCase       )


				def __UpperCamelCase						(							self      :  Any       )		->     int:
											A      						=    os.O_RDWR | os.O_CREAT | os.O_TRUNC
											A      						=    os.open(self._lock_file						, __UpperCamelCase       )

											try:
																		fcntl.flock(__UpperCamelCase						, fcntl.LOCK_EX | fcntl.LOCK_NB       )
											except OSError:
																		os.close(__UpperCamelCase       )
											else:
																		A      						=    fd
											return None


				def __UpperCamelCase						(							self      :  Optional[int]       )		->     int:
											# Do not remove the lockfile:
											#
											#   https://github.com/benediktschmitt/py-filelock/issues/31
											#   https://stackoverflow.com/questions/17708885/flock-removing-locked-file-without-race-condition
											A      						=    self._lock_file_fd
											A      						=    None
											fcntl.flock(__UpperCamelCase						, fcntl.LOCK_UN       )
											os.close(__UpperCamelCase       )
											return None





class        lowerCAmelCase__					(  _lowerCamelCase       ):


				def __UpperCamelCase						(							self      :  int       )		->     Optional[int]:
											A      						=    os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_TRUNC
											try:
																		A      						=    os.open(self._lock_file						, __UpperCamelCase       )
											except OSError:
																		pass
											else:
																		A      						=    fd
											return None


				def __UpperCamelCase						(							self      :  Optional[Any]       )		->     List[str]:
											os.close(self._lock_file_fd       )
											A      						=    None

											try:
																		os.remove(self._lock_file       )
											# The file is already deleted and that's what we want.
											except OSError:
																		pass
											return None





__snake_case     :List[str]			       =None

if msvcrt:
				__snake_case     :List[Any]			       =WindowsFileLock
elif fcntl:
				__snake_case     :Any			       =UnixFileLock
else:
				__snake_case     :Tuple			       =SoftFileLock

				if warnings is not None:
								warnings.warn('only soft file lock is available')