"""simple docstring"""



import importlib.metadata
import warnings
from copy import deepcopy

from packaging import version

from ..utils import logging
from .import_utils import is_accelerate_available, is_bitsandbytes_available


if is_bitsandbytes_available():
   import bitsandbytes as bnb
   import torch
   import torch.nn as nn

   from ..pytorch_utils import ConvaD

if is_accelerate_available():
   from accelerate import init_empty_weights
   from accelerate.utils import find_tied_parameters

SCREAMING_SNAKE_CASE__:Tuple			=	logging.get_logger(__name__)



def 					_lowerCamelCase(					a ,  a ,  a ,  a=None ,  a=None							):
       # Recurse if needed
       if "." in tensor_name:
              __a     				=  tensor_name.split("."							)
              for split in splits[:-1]:
                     __a     				=  getattr(a ,  a							)
                     if new_module is None:
                            raise ValueError(F"{module} has no attribute {split}."							)
                     __a     				=  new_module
              __a     				=  splits[-1]

       if tensor_name not in module._parameters and tensor_name not in module._buffers:
              raise ValueError(F"{module} does not have a parameter or a buffer named {tensor_name}."							)
       __a     				=  tensor_name in module._buffers
       __a     				=  getattr(a ,  a							)

       if old_value.device == torch.device("meta"							) and device not in ["meta", torch.device("meta"							)] and value is None:
              raise ValueError(F"{tensor_name} is on the meta device, we need a `value` to put in on {device}."							)

       __a     				=  False
       __a     				=  False
       if is_buffer or not is_bitsandbytes_available():
              __a     				=  False
              __a     				=  False
       else:
              __a     				=  hasattr(bnb.nn ,  "Params4bit"							) and isinstance(module._parameters[tensor_name] ,  bnb.nn.Paramsabit							)
              __a     				=  isinstance(module._parameters[tensor_name] ,  bnb.nn.IntaParams							)

       if is_abit or is_abit:
              __a     				=  module._parameters[tensor_name]
              if param.device.type != "cuda":
                     if value is None:
                            __a     				=  old_value.to(a							)
                     elif isinstance(a ,  torch.Tensor							):
                            __a     				=  value.to("cpu"							)
                            if value.dtype == torch.inta:
                                   __a     				=  version.parse(importlib.metadata.version("bitsandbytes"							)							) > version.parse(
                                       "0.37.2"							)
                                   if not is_abit_serializable:
                                          raise ValueError(
                                              "Detected int8 weights but the version of bitsandbytes is not compatible with int8 serialization. "
                                              "Make sure to download the latest `bitsandbytes` version. `pip install --upgrade bitsandbytes`."							)
                     else:
                            __a     				=  torch.tensor(a ,  device="cpu"							)

                     # Support models using `Conv1D` in place of `nn.Linear` (e.g. gpt2) by transposing the weight matrix prior to quantization.
                     # Since weights are saved in the correct "orientation", we skip transposing when loading.
                     if issubclass(module.source_cls ,  a							) and fpaa_statistics is None:
                            __a     				=  new_value.T

                     __a     				=  old_value.__dict__
                     if is_abit:
                            __a     				=  bnb.nn.IntaParams(a ,  requires_grad=a ,  **a							).to(a							)
                     elif is_abit:
                            __a     				=  bnb.nn.Paramsabit(a ,  requires_grad=a ,  **a							).to(a							)

                     __a     				=  new_value
                     if fpaa_statistics is not None:
                            setattr(module.weight ,  "SCB" ,  fpaa_statistics.to(a							)							)

       else:
              if value is None:
                     __a     				=  old_value.to(a							)
              elif isinstance(a ,  torch.Tensor							):
                     __a     				=  value.to(a							)
              else:
                     __a     				=  torch.tensor(a ,  device=a							)

              if is_buffer:
                     __a     				=  new_value
              else:
                     __a     				=  nn.Parameter(a ,  requires_grad=old_value.requires_grad							)
                     __a     				=  new_value



def 					_lowerCamelCase(					a ,  a=None ,  a=None ,  a=None ,  a=False							):
       for name, module in model.named_children():
              if current_key_name is None:
                     __a     				=  []
              current_key_name.append(a							)

              if (isinstance(a ,  nn.Linear							) or isinstance(a ,  a							)) and name not in modules_to_not_convert:
                     # Check if the current key is not in the `modules_to_not_convert`
                     if not any(key in ".".join(a							) for key in modules_to_not_convert							):
                            with init_empty_weights():
                                   if isinstance(a ,  a							):
                                          __a				, __a     				=  module.weight.shape
                                   else:
                                          __a     				=  module.in_features
                                          __a     				=  module.out_features

                                   if quantization_config.quantization_method() == "llm_int8":
                                          __a     				=  bnb.nn.LinearabitLt(
                                              a ,  a ,  module.bias is not None ,  has_fpaa_weights=quantization_config.llm_inta_has_fpaa_weight ,  threshold=quantization_config.llm_inta_threshold ,  )
                                          __a     				=  True
                                   else:
                                          if (
                                              quantization_config.llm_inta_skip_modules is not None
                                              and name in quantization_config.llm_inta_skip_modules
                                          ):
                                                 pass
                                          else:
                                                 __a     				=  bnb.nn.Linearabit(
                                                     a ,  a ,  module.bias is not None ,  quantization_config.bnb_abit_compute_dtype ,  compress_statistics=quantization_config.bnb_abit_use_double_quant ,  quant_type=quantization_config.bnb_abit_quant_type ,  )
                                                 __a     				=  True
                    # Store the module class in case we need to transpose the weight later
                                   __a     				=  type(a							)
                                   # Force requires grad to False to avoid unexpected errors
                                   model._modules[name].requires_grad_(a							)
              if len(list(module.children()							)							) > 0:
                     __a				, __a     				=  _replace_with_bnb_linear(
                         a ,  a ,  a ,  a ,  has_been_replaced=a ,  )
              # Remove the last key for recursion
              current_key_name.pop(-1							)
       return model, has_been_replaced



def 					_lowerCamelCase(					a ,  a=None ,  a=None ,  a=None							):
       __a     				=  ["lm_head"] if modules_to_not_convert is None else modules_to_not_convert
       __a				, __a     				=  _replace_with_bnb_linear(
           a ,  a ,  a ,  a							)

       if not has_been_replaced:
              logger.warning(
                  "You are loading your model in 8bit or 4bit but no linear modules were found in your model."
                  " Please double check your model architecture, or submit an issue on github if you think this is"
                  " a bug."							)

       return model



def 					_lowerCamelCase(					*a ,  **a							):
       warnings.warn(
           "`replace_8bit_linear` will be deprecated in a future version, please use `replace_with_bnb_linear` instead" ,  a ,  )
       return replace_with_bnb_linear(*a ,  **a							)



def 					_lowerCamelCase(					*a ,  **a							):
       warnings.warn(
           "`set_module_8bit_tensor_to_device` will be deprecated in a future version, please use `set_module_quantized_tensor_to_device` instead" ,  a ,  )
       return set_module_quantized_tensor_to_device(*a ,  **a							)




def 					_lowerCamelCase(					a							):
       __a     				=  deepcopy(a							)  # this has 0 cost since it is done inside `init_empty_weights` context manager`
       tied_model.tie_weights()

       __a     				=  find_tied_parameters(a							)
       # For compatibility with Accelerate < 0.18
       if isinstance(a ,  a							):
              __a     				=  sum(list(tied_params.values()							) ,  []							) + list(tied_params.keys()							)
       else:
              __a     				=  sum(a ,  []							)
       __a     				=  len(a							) > 0

       # Check if it is a base model
       __a     				=  not hasattr(a ,  model.base_model_prefix							)

       # Ignore this for base models (BertModel, GPT2Model, etc.)
       if (not has_tied_params) and is_base_model:
              return []

       # otherwise they have an attached head
       __a     				=  list(model.named_children()							)
       __a     				=  [list_modules[-1][0]]

       # add last module together with tied weights
       __a     				=  set(a							) - set(a							)
       __a     				=  list(set(a							)							) + list(a							)

       # remove ".weight" from the keys
       __a     				=  [".weight", ".bias"]
       __a     				=  []
       for name in list_untouched:
              for name_to_remove in names_to_remove:
                     if name_to_remove in name:
                            __a     				=  name.replace(a ,  ""							)
              filtered_module_names.append(a							)

       return filtered_module_names

"""simple docstring"""



import contextlib
from multiprocessing import Pool, RLock

from tqdm.auto import tqdm

from ..utils import experimental, logging


SCREAMING_SNAKE_CASE__:Union[str, Any]			=	logging.get_logger(__name__)






class 				snake_case__     :
 _snake_case   :			List[str]           =		None



@experimental
def 					_lowerCamelCase(					a ,  a ,  a ,  a ,  a ,  a ,  a							):
       if ParallelBackendConfig.backend_name is None:
              return _map_with_multiprocessing_pool(
                  a ,  a ,  a ,  a ,  a ,  a ,  a							)

       return _map_with_joblib(a ,  a ,  a ,  a ,  a ,  a ,  a							)



def 					_lowerCamelCase(					a ,  a ,  a ,  a ,  a ,  a ,  a							):
       __a     				=  num_proc if num_proc <= len(a							) else len(a							)
       __a     				=  []  # We organize the splits ourselve (contiguous splits)
       for index in range(a							):
              __a     				=  len(a							) // num_proc
              __a     				=  len(a							) % num_proc
              __a     				=  div * index + min(a ,  a							)
              __a     				=  start + div + (1 if index < mod else 0)
              split_kwds.append((function, iterable[start:end], types, index, disable_tqdm, desc)							)

       if len(a							) != sum(len(i[1]							) for i in split_kwds							):
              raise ValueError(
                  F"Error dividing inputs iterable among processes. "
                  F"Total number of objects {len(a							)}, "
                  F"length: {sum(len(i[1]							) for i in split_kwds							)}"							)

       logger.info(
           F"Spawning {num_proc} processes for {len(a							)} objects in slices of {[len(i[1]							) for i in split_kwds]}"							)
       __a				, __a     				=  None, None
       if not disable_tqdm:
              __a				, __a     				=  (RLock(),), tqdm.set_lock
       with Pool(a ,  initargs=a ,  initializer=a							) as pool:
              __a     				=  pool.map(a ,  a							)
       logger.info(F"Finished {num_proc} processes"							)
       __a     				=  [obj for proc_res in mapped for obj in proc_res]
       logger.info(F"Unpacked {len(a							)} objects"							)

       return mapped



def 					_lowerCamelCase(					a ,  a ,  a ,  a ,  a ,  a ,  a							):
       # progress bar is not yet supported for _map_with_joblib, because tqdm couldn't accurately be applied to joblib,
       # and it requires monkey-patching joblib internal classes which is subject to change
       import joblib

       with joblib.parallel_backend(ParallelBackendConfig.backend_name ,  n_jobs=a							):
              return joblib.Parallel()(
                  joblib.delayed(a							)((function, obj, types, None, True, None)							) for obj in iterable							)




@experimental
@contextlib.contextmanager
def 					_lowerCamelCase(					a							):
       __a     				=  backend_name

       if backend_name == "spark":
              from joblibspark import register_spark

              register_spark()

              # TODO: call create_cache_and_write_probe if "download" in steps
              # TODO: raise NotImplementedError when Dataset.map etc is called

       try:
              yield
       finally:
              __a     				=  None
