[INFO|modeling_utils.py:2766] 2024-11-2110:19:00,213 >> Model weights saved in /home/dell/sdb/saves/Qwen2-0___5B-Instruct/freeze/sft/checkpoint-25/model.safetensors
PGSQL
权重文件保存为 model.safetensors 格式。
保存分词器文件
1 2
[INFO|tokenization_utils_base.py:2702] 2024-11-2110:19:00,214 >> tokenizer config file saved in /home/dell/sdb/saves/Qwen2-0___5B-Instruct/freeze/sft/checkpoint-25/tokenizer_config.json [INFO|tokenization_utils_base.py:2711] 2024-11-2110:19:00,214 >> Special tokens file saved in /home/dell/sdb/saves/Qwen2-0___5B-Instruct/freeze/sft/checkpoint-25/special_tokens_map.json
# Save the model if state_dict isNone: # if any model parameters are offloaded, make module map if ( # 检查模型是否有设备映射属性 hasattr(self, "hf_device_map") # 确认设备映射到多个设备 andlen(set(self.hf_device_map.values())) > 1 # 判断是否有部分模型参数被 offload(存储到 CPU 或磁盘)。 and ("cpu"inself.hf_device_map.values() or"disk"inself.hf_device_map.values()) ): # 发出警告,提示用户 CPU 的空闲内存需要大于 shard_size(默认值为 5GB)。 warnings.warn( "Attempting to save a model with offloaded modules. Ensure that unallocated cpu memory exceeds the `shard_size` (5GB default)" )
# 遍历 model_to_save 的所有子模块。named_modules() 方法返回所有模块的名字和模块本身。准备为每个模块提取参数字典(state_dict)。 for name, module in model_to_save.named_modules(): if name == "": continue # 获取当前模块的参数字典(state_dict)。 module_state_dict = module.state_dict() # 将模块名和参数名组合,记录到 module_map 中。为每个参数生成唯一的键名:模块名.参数名。在 module_map 中记录键名和模块的对应关系,用于后续加载这些参数。 for key in module_state_dict: module_map[name + f".{key}"] = module
# Save the model filename_to_tensors = state_dict_split.filename_to_tensors.items() if module_map: filename_to_tensors = logging.tqdm(filename_to_tensors, desc="Saving checkpoint shards") for shard_file, tensors in filename_to_tensors: shard = {tensor: state_dict[tensor] for tensor in tensors} # remake shard with onloaded parameters if necessary if module_map: if accelerate_version < version.parse("0.31"): raise ImportError( f"You need accelerate version to be greater or equal than 0.31 to save models with offloaded parameters. Detected version {accelerate_version}. " f"Please upgrade accelerate with `pip install -U accelerate`" ) # init state_dict for this shard shard_state_dict = {name: "" for name in shard} for module_name in shard: module = module_map[module_name] # update state dict with onloaded parameters shard_state_dict = get_state_dict_from_offload(module, module_name, shard_state_dict)
# assign shard to be the completed state dict shard = shard_state_dict del shard_state_dict gc.collect()
if safe_serialization: # At some point we will need to deal better with save_function (used for TPU and other distributed # joyfulness), but for now this enough. safe_save_file(shard, os.path.join(save_directory, shard_file), metadata={"format": "pt"}) else: save_function(shard, os.path.join(save_directory, shard_file))
MIPSASM
代码核心逻辑概述:
分片处理:将大模型的参数按需分片保存,减少内存占用。
设备卸载管理:处理可能被分配到不同设备(如 CPU 或磁盘)的参数,从设备或磁盘加载卸载的参数到内存中,确保能够正确重新加载。
# Save the config ifis_main_process: ifnot_hf_peft_config_loaded: model_to_save.config.save_pretrained(save_directory) ifself.can_generate(): # generation config built from the model config + the model config holds generation kwargs -> generate # may revert to legacy behavior if the two don't match if ( model_to_save.generation_config._from_model_config and model_to_save.config._has_non_default_generation_parameters() ): new_generation_config = GenerationConfig.from_model_config(model_to_save.config) if new_generation_config != model_to_save.generation_config: logger.warning( "Your generation config was originally created from the model config, but the model " "config has changed since then. Unless you pass the `generation_config` argument to this " "model's `generate` calls, they will revert to the legacy behavior where the base " "`generate` parameterization is loaded from the model config instead. " "To avoid this behavior and this warning, we recommend you to overwrite the generation " "config model attribute before calling the model's `save_pretrained`, preferably also " "removing any generation kwargs from the model config. This warning will be raised to an " "exception in v4.41." ) model_to_save.generation_config.save_pretrained(save_directory)
def persistent_id(obj): if isinstance(obj, torch.storage.TypedStorage) or torch.is_storage(obj):
if isinstance(obj, torch.storage.TypedStorage): # TODO: Once we decide to break serialization FC, this case # can be deleted storage = obj._untyped_storage storage_dtype = obj.dtype storage_type_str = obj._pickle_storage_type() storage_type = getattr(torch, storage_type_str) storage_numel = obj._size()
if storage.data_ptr() != 0: if storage.data_ptr() in storage_dtypes: if storage_dtype != storage_dtypes[storage.data_ptr()]: raise RuntimeError( 'Cannot save multiple tensors or storages that ' 'view the same data as different types') else: storage_dtypes[storage.data_ptr()] = storage_dtype
# Writeeach tensor to a file named tensor/the_tensor_key in the zip archive for keyin sorted(serialized_storages.keys()): name = f'data/{key}' storage = serialized_storages[key] # given that we copy things around anyway, we might use storage.cpu() # this means to that toget tensors serialized, you need to implement # .cpu() on the underlying Storage ifstorage.device.type != 'cpu': storage = storage.cpu() # Now that it ison the CPU we can directly copy it into the zip file num_bytes = storage.nbytes() zip_file.write_record(name, storage, num_bytes)