参数高效微调PEFT(三)快速入门LoRA、AdaLoRA

参数高效微调PEFT(三)快速入门LoRA、AdaLoRA

  • 我们已经了解了HuggingFace中peft库的几种高效微调方法。

参数高效微调PEFT(一)快速入门BitFit、Prompt Tuning、Prefix Tuning

参数高效微调PEFT(二)快速入门P-Tuning、P-Tuning V2

  • 今天我们继续了解大火的高效微调方法LoRA以及改进的AdaLoRA。
  • 另外,QLoRA是模型量化 (Quantilization) 与LoRA的结合,我们会在后面低精度微调时(微调Chat GLM3的7B模型)进行介绍。
  • 注意:我们到目前都是以单精度FP32加载模型,模型本身占用的显存大小并没有改变。

1 LoRA

  • 将小型网络模块添加到PLMs中,保持基础模型保持不变的情况下仅针对每个任务微调这些模块,可以用于所有任务。
  • 这样,只需引入和更新少量任务特定的参数,就可以适配下游的任务,大大提高了预训练模型的实用性。如:Adapter tuning、Prefix tuning、Prompt Tuning等。
  • 这类方法虽然大大减少了内存消耗,但是这些方法存在一些问题。
    • 比如:Adapter tuning引入了推理延时;
    • Prefix tuning或Prompt tuning直接优化Prefix和Prompt是非单调的,比较难收敛,并且消耗了输入的token。
  • LoRA训练完成后,可以将两个低秩矩阵与原始模型中的权重进行合并,合并后的模型与原始模型无异,避免了推理期间Prompt系列方法带来的额外计算量

1.1 LoRA简介

  • 论文地址:LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS (2106)

  • LORA的核心思想就是通过低秩分解来模拟参数的改变量,从而以极小的参数量来实现大模型的间接训练。

    • 预训练模型中存在一个极小的内在维度,这个内在维度是发挥核心作用的地方。
    • 在微调的过程中,权重的更新依然也有如此特点,即也存在一个内在维度 (内在秩)。
  • 如下图所示,可训练层维度和预训练模型层维度一致为d,先将维度d通过全连接层降维至r,再从r通过全连接层映射回d维度。其中,r<<d,r是矩阵的秩,这样矩阵计算就从 d × d d × d d×d变为 d × r + r × d d × r + r × d d×r+r×d,参数量减少很多。

    • 在下游任务训练时,固定模型的其他参数,只优化新增的两个矩阵的权重参数,将PLM跟新增的通路两部分的结果加起来作为最终的结果(两边通路的输入、输出维度都是一致的),即 h = W x + B A x h=Wx+BAx h=Wx+BAx
    • 第一个矩阵的A的权重参数会通过高斯函数初始化(注意:A矩阵不能初始化为零矩阵);
    • 第二个矩阵的B的权重参数则会初始化为零矩阵,这样能保证训练开始时新增的通路 B A = 0 BA=0 BA=0,从而对模型结果没有影响。

在这里插入图片描述

  • 训练完成后,可以将两个低秩矩阵与原始模型中的权重进行合并,合并后的模型与原始模型无异,避免了推理期间Prompt系列方法带来的额外计算量

  • 我们知道Transformer的权重矩阵包括Attention模块里用于计算query,key,value的Wq、Wk、Wv、多头attention的Wo以及MLP层的权重矩阵。如下图,LoRA只应用于Attention模块中的4种权重矩阵,而且通过消融实验发现同时调整 Wq 和 Wv 会产生最佳结果。

在这里插入图片描述

  • 如下图所示,可以发现保证权重矩阵的种类的数量比起增加隐藏层维度r更为重要,增加r并不一定能覆盖更加有意义的子空间。

在这里插入图片描述

  • 通常情况下,r选择为4,8,16即可,peft库中默认为8。

在这里插入图片描述

  • 在众多数据集上LoRA在只训练极少量参数的前提下,最终在性能上能和全量微调匹配,甚至在某些任务上优于全量微调。

1.2 LoRA源码分析

我们在peft库默认配置下(LoraConfig(task_type=TaskType.CAUSAL_LM)),进行源码分析。

from peft import LoraConfig, TaskType, get_peft_model
config = LoraConfig(task_type=TaskType.CAUSAL_LM)
model = get_peft_model(model, config)

LoRA的代码主要分为三个部分:初始化、推理和参数合并。

1.2.1 LoRA初始化分析

我们先看下LoRA初始化,默认设置下,LoRA为线性层class Linear(nn.Linear, LoRALayer)

  • LoRA仅支持nn.Linear、nn.Embedding和nn.Conv2d,微调线性层是常见的做法。

  • 通过MAPPING找到PeftModelForCausalLM进行初始化

# peft\mapping.py

def get_peft_model(model: PreTrainedModel, peft_config: PeftConfig, adapter_name: str = "default") -> PeftModel:
    ......
    # 1、判断任务类型 如果不是['SEQ_CLS', 'SEQ_2_SEQ_LM', 'CAUSAL_LM', 'TOKEN_CLS', 'QUESTION_ANS', 'FEATURE_EXTRACTION']里类型 而且 不是prompt_learning
    if peft_config.task_type not in MODEL_TYPE_TO_PEFT_MODEL_MAPPING.keys() and not peft_config.is_prompt_learning:
        return PeftModel(model, peft_config, adapter_name=adapter_name)
    # 2、prompt_learning
    if peft_config.is_prompt_learning:
        peft_config = _prepare_prompt_learning_config(peft_config, model_config)
    # 3、通过mapping找到peft.peft_model.PeftModelForCausalLM
    return MODEL_TYPE_TO_PEFT_MODEL_MAPPING[peft_config.task_type](model, peft_config, adapter_name=adapter_name)
  • 然后我们会进入PeftModelForCausalLM的初始化,此时会调用父类PeftModel的初始化方法
# peft\peft_model.py
class PeftModelForCausalLM(PeftModel):
    
    def __init__(self, model, peft_config: PeftConfig, adapter_name="default"):
        # 调用父类PeftModel的初始化方法
        super().__init__(model, peft_config, adapter_name)
        self.base_model_prepare_inputs_for_generation = self.base_model.prepare_inputs_for_generation
    
    ......

  • 父类PeftModel的初始化中,会进行LoraModel的初始化;在LoraModel中,会进行父类BaseTuner的初始化
# peft\peft_model.py
class PeftModel(PushToHubMixin, torch.nn.Module):

    def __init__(self, model: PreTrainedModel, peft_config: PeftConfig, adapter_name: str = "default"):
        super().__init__()
        self.base_model = model
        self.config = getattr(self.base_model, "config", {"model_type": "custom"})
        self.modules_to_save = None
        self.peft_config = {}
        self.active_adapter = adapter_name
        self.peft_type = peft_config.peft_type
        if not peft_config.is_prompt_learning:
            # 不是prompt_learning,我们进入此分支
            self.peft_config[adapter_name] = peft_config
            # 通过PEFT_TYPE_TO_MODEL_MAPPING我们获取peft.tuners.lora.LoraModel
            # 然后会进入LoraModel的初始化
            self.base_model = PEFT_TYPE_TO_MODEL_MAPPING[peft_config.peft_type](
                self.base_model, self.peft_config, adapter_name
            )
            self.set_additional_trainable_modules(peft_config, adapter_name)
        else:
            self.add_adapter(adapter_name, peft_config)
        ......

        
# peft\tuners\lora.py
class LoraModel(BaseTuner):
    
    def __init__(self, model, config, adapter_name) -> None:
        # 进行BaseTuner的初始化
		super().__init__(model, config, adapter_name)    
        
    .....    
  • 在父类BaseTuner中,会调用inject_adapter方法。
  • inject_adapter中遍历每一个key,调用_create_and_replace,
  • target默认为线性层,会调用_create_new_module方法,返回一个new_module,然后将旧的module替换为new_module ,即加了LoRA后的module。
  • create_new_module会进行new_module = Linear(adapter_name, in_features, out_features, bias=bias, **kwargs),即peft\tuners\lora.py中Linear的初始化。
# peft\tuners\tuners_utils.py
class BaseTuner(nn.Module, ABC):
    def __init__(self, model, peft_config: Union[PeftConfig, dict[str, PeftConfig]], adapter_name: str) -> None:
        super().__init__()

        self.model = model
        ......
        # 会掉用inject_adapter方法
        self.inject_adapter(self.model, adapter_name)

        # Copy the peft_config in the injected model.
        self.model.peft_config = self.peft_config
    ......     
    
    
 # peft\tuners\lora.py
 def inject_adapter(self, model: nn.Module, adapter_name: str):
        peft_config = self.peft_config[adapter_name]
        is_target_modules_in_base_model = False
        key_list = [key for key, _ in model.named_modules()]

        model_config = getattr(model, "config", {"model_type": "custom"})
        if hasattr(model_config, "to_dict"):
            model_config = model_config.to_dict()
        # 获取高效微调的默认设置项
        peft_config = self._prepare_adapter_config(peft_config, model_config)
        
        # 遍历每一个key
        for key in key_list:
            
            is_target_modules_in_base_model = True
            # 例如,key= 'transformer.h.0.self_attention.query_key_value'
            # parent = BloomAttention(
            #  (query_key_value): Linear(in_features=64, out_features=192, bias=True)
            #  (dense): Linear(in_features=64, out_features=64, bias=True)
            #  (attention_dropout): Dropout(p=0.0, inplace=False)
            # )
            
            # target = Linear(in_features=64, out_features=192, bias=True)
            # target_name = 'query_key_value'
            parent, target, target_name = _get_submodules(model, key)

            optionnal_kwargs = {
                "loaded_in_8bit": getattr(model, "is_loaded_in_8bit", False),
                "loaded_in_4bit": getattr(model, "is_loaded_in_4bit", False),
                "current_key": key,
            }
            # 
            self._create_and_replace(peft_config, adapter_name, target, target_name, parent, **optionnal_kwargs)

        ......

                    
    # peft\tuners\lora.py
	def _create_and_replace(
        self,
        lora_config,
        adapter_name,
        target,
        target_name,
        parent,
        **optionnal_kwargs,
    ):
        ......

        # TODO: better deal with that
        if isinstance(target, LoraLayer) and isinstance(target, torch.nn.Conv2d):
            target.update_layer_conv2d(
                adapter_name,
                lora_config.r,
                lora_config.lora_alpha,
                lora_config.lora_dropout,
                lora_config.init_lora_weights,
            )
        ......
        else:
            # target默认为线性层,会进入此分支
            new_module = self._create_new_module(lora_config, adapter_name, target, **kwargs)   
            # 此方法会将原始module进行替换,替换为加上lora后的
            self._replace_module(parent, target_name, new_module, target)                    
# 高效微调的默认设置项
LoraConfig(
    peft_type=<PeftType.LORA: 'LORA'>           # peft的类型
  , auto_mapping=None
  , base_model_name_or_path=''
  , revision=None
  , task_type=<TaskType.CAUSAL_LM: 'CAUSAL_LM'> # 任务类型
  , inference_mode=False
  , r=8                                # 秩大小,一般4,8,16,小数据集一般设置更小的r(1,2)
  , target_modules=['query_key_value'] # 指定应用lora的目标模块,Bloom模型默认为query_key_value,可以使用正则
  , lora_alpha=8         # 尺度缩放参数,ΔW按α/r缩放,即scaling[adapter_name]=lora_alpha/r,默认为1
  , lora_dropout=0.0     # lora层的dropout比率
  , fan_in_fan_out=False
  , bias='none'          # 偏差可以是“无”、“全部”或“lora_only”。如果是“all”或“lora_only”,则相应的偏差将在训练期间更新
  , modules_to_save=None # 全量微调时,模型的layer名称
  , init_lora_weights=True
  , layers_to_transform=None
  , layers_pattern=None
)
  • Linear初始化中,重要的代码就是update_layer

  • update_layer中,就会初始化秩为r的可训练参数A和B

  • new_module = Linear(
      in_features=64, out_features=192, bias=True
      (lora_dropout): ModuleDict(
        (default): Identity()
      )
      (lora_A): ModuleDict(
        (default): Linear(in_features=64, out_features=8, bias=False)
      )
      (lora_B): ModuleDict(
        (default): Linear(in_features=8, out_features=192, bias=False)
      )
      (lora_embedding_A): ParameterDict()
      (lora_embedding_B): ParameterDict()
    )
    
  • 上面就是Linear初始化后的模块,即new_module。初始化后,就会将之前的module进行替换。

# 替换前
BloomAttention(
  (query_key_value): Linear(in_features=64, out_features=192, bias=True)
  (dense): Linear(in_features=64, out_features=64, bias=True)
  (attention_dropout): Dropout(p=0.0, inplace=False)
)

# 通过下面代码进行替换
# peft\tuners\lora.py中的_create_and_replace方法
new_module = self._create_new_module(lora_config, adapter_name, target, **kwargs)
self._replace_module(parent, target_name, new_module, target)

# 替换后
BloomAttention(
  (query_key_value): Linear(
    in_features=64, out_features=192, bias=True
    (lora_dropout): ModuleDict(
      (default): Identity()
    )
    (lora_A): ModuleDict(
      (default): Linear(in_features=64, out_features=8, bias=False)
    )
    (lora_B): ModuleDict(
      (default): Linear(in_features=8, out_features=192, bias=False)
    )
    (lora_embedding_A): ParameterDict()
    (lora_embedding_B): ParameterDict()
  )
  (dense): Linear(in_features=64, out_features=64, bias=True)
  (attention_dropout): Dropout(p=0.0, inplace=False)
)
  • 上面就是替换前后BloomAttention模块的结构。
# peft\tuners\lora.py
class Linear(nn.Linear, LoraLayer):
    # Lora implemented in a dense layer
    def __init__(
        self,
        adapter_name: str,
        in_features: int,
        out_features: int,
        r: int = 0,
        lora_alpha: int = 1,
        lora_dropout: float = 0.0,
        fan_in_fan_out: bool = False,  # Set this to True if the layer to replace stores weight like (fan_in, fan_out)
        is_target_conv_1d_layer: bool = False,
        **kwargs,
    ):
        init_lora_weights = kwargs.pop("init_lora_weights", True)

        nn.Linear.__init__(self, in_features, out_features, **kwargs)
        LoraLayer.__init__(self, in_features=in_features, out_features=out_features)
        # Freezing the pre-trained weight matrix
        self.weight.requires_grad = False

        self.fan_in_fan_out = fan_in_fan_out
        if fan_in_fan_out:
            self.weight.data = self.weight.data.T

        nn.Linear.reset_parameters(self)
        # 重要代码
        self.update_layer(adapter_name, r, lora_alpha, lora_dropout, init_lora_weights)
        self.active_adapter = adapter_name
        self.is_target_conv_1d_layer = is_target_conv_1d_layer
        ......
 def update_layer(self, adapter_name, r, lora_alpha, lora_dropout, init_lora_weights):
        self.r[adapter_name] = r
        self.lora_alpha[adapter_name] = lora_alpha
        if lora_dropout > 0.0:
            # dropout
            lora_dropout_layer = nn.Dropout(p=lora_dropout)
        else:
            # 默认设置
            lora_dropout_layer = nn.Identity()

        self.lora_dropout.update(nn.ModuleDict({adapter_name: lora_dropout_layer}))
        # Actual trainable parameters
        if r > 0:
            # 如果秩大于0,就初始化秩为R的可训练参数A和B
            self.lora_A.update(nn.ModuleDict({adapter_name: nn.Linear(self.in_features, r, bias=False)}))
            self.lora_B.update(nn.ModuleDict({adapter_name: nn.Linear(r, self.out_features, bias=False)}))
            # 指定lora_alpha参数,用于平衡LORA 和 基础模型的贡献
            # 这里scaling默认为1
            self.scaling[adapter_name] = lora_alpha / r
        if init_lora_weights:
            self.reset_lora_parameters(adapter_name)
        self.to(self.weight.device)        

1.2.2 前向过程

  • 前向过程中,最终会调用BloomForCausalLM的前向传播方法。
LoraModel(
  (model): BloomForCausalLM(
    (transformer): BloomModel(
      (word_embeddings): Embedding(250880, 64)
      (word_embeddings_layernorm): LayerNorm((64,), eps=1e-05, elementwise_affine=True)
      (h): ModuleList(
        (0-1): 2 x BloomBlock(
          (input_layernorm): LayerNorm((64,), eps=1e-05, elementwise_affine=True)
          (self_attention): BloomAttention(
            # 在BloomAttention的query_key_value中,使用LoRA进行微调
            (query_key_value): Linear(
              in_features=64, out_features=192, bias=True
              (lora_dropout): ModuleDict(
                (default): Identity()
              )
              (lora_A): ModuleDict(
                (default): Linear(in_features=64, out_features=8, bias=False)
              )
              (lora_B): ModuleDict(
                (default): Linear(in_features=8, out_features=192, bias=False)
              )
              (lora_embedding_A): ParameterDict()
              (lora_embedding_B): ParameterDict()
            )
            (dense): Linear(in_features=64, out_features=64, bias=True)
            (attention_dropout): Dropout(p=0.0, inplace=False)
          )
          (post_attention_layernorm): LayerNorm((64,), eps=1e-05, elementwise_affine=True)
          (mlp): BloomMLP(
            (dense_h_to_4h): Linear(in_features=64, out_features=256, bias=True)
            (gelu_impl): BloomGelu()
            (dense_4h_to_h): Linear(in_features=256, out_features=64, bias=True)
          )
        )
      )
      (ln_f): LayerNorm((64,), eps=1e-05, elementwise_affine=True)
    )
    (lm_head): Linear(in_features=64, out_features=250880, bias=False)
  )
)
  • 在BloomAttention中,会调用peft\tuners\lora.py中Linear的前向传播(如下代码)。
  • 注意:self.lora_A和self.lora_B类型为ModuleDict,这是因为LoRA有高级用法,我们以后再介绍:
    • 一个主模型,可以使用多个适配器(默认self.active_adapter=default)
    • 可以切换适配器
    • 可以禁用适配器,获取原始结果
    # peft\tuners\lora.py
    def forward(self, x: torch.Tensor):
        
        previous_dtype = x.dtype
        if self.active_adapter not in self.lora_A.keys():
            return F.linear(x, transpose(self.weight, self.fan_in_fan_out), bias=self.bias)
        
        if self.disable_adapters:
            if self.r[self.active_adapter] > 0 and self.merged:
                self.unmerge()
            result = F.linear(x, transpose(self.weight, self.fan_in_fan_out), bias=self.bias)
        # 不禁用adapters,且秩r > 0,且不合并   
        elif self.r[self.active_adapter] > 0 and not self.merged:
            # 1、result = torch.Size([1, 48, 192])
            result = F.linear(x, transpose(self.weight, self.fan_in_fan_out), bias=self.bias)

            x = x.to(self.lora_A[self.active_adapter].weight.dtype)
            # 2、核心代码
            # x = torch.Size([1, 48, 64])
            # self.lora_A['default'] = Linear(in_features=64, out_features=8, bias=False)
            # x经过self.lora_A,torch.Size([1, 48, 8])
            # self.lora_B['default'] = Linear(in_features=8, out_features=192, bias=False)
            # x经过self.lora_B,torch.Size([1, 48, 192])
            # 然后result相加合并,即h = Wx + BAx
            result += (
                self.lora_B[self.active_adapter](
                    self.lora_A[self.active_adapter](self.lora_dropout[self.active_adapter](x))
                )
                * self.scaling[self.active_adapter]
            )
        else:
            result = F.linear(x, transpose(self.weight, self.fan_in_fan_out), bias=self.bias)

        result = result.to(previous_dtype)

        return result

1.3 LoRA轻量微调bloom模型

同样,我们只需要在加载原模型后、配置训练器前加peft的代码即可。

from peft import LoraConfig, TaskType, get_peft_model

config = LoraConfig(
	task_type=TaskType.CAUSAL_LM
	# , target_modules=".*\.1.*query_key_value" 指定要添加LoRA的目标模块(支持正则)
	# , modules_to_save=["word_embeddings"] 全量微调时,模型的layer名称
	, modules_to_save=None
)

model = get_peft_model(model, config)

# 打印可训练参数
model.print_trainable_parameters()

trainable params: 786,432 || all params: 346,555,392 || trainable%: 0.22692822508443325
  • 配置训练器、模型训练及推理和参数高效微调PEFT(一)快速入门BitFit、Prompt Tuning、Prefix Tuning中2.1一样。
  • 显存消耗情况:
(base) root@autodl-container-adbc11ae52-f2ebff02:~# nvidia-smi   
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 525.89.02    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:41:00.0 Off |                  N/A |
| 35%   59C    P2   143W / 250W |   2810MiB / 11264MiB |     31%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

1.4 模型保存

LoRA训练完成后,可以将两个低秩矩阵与原始模型中的权重进行合并,合并后的模型与原始模型无异,避免了推理期间Prompt系列方法带来的额外计算量

from transformers import AutoModelForCausalLM, AutoTokenizer

from peft import PeftModel


# 1、加载基础模型
model_path = r'/root/autodl-fs/models/langboat/bloom-389m-zh'

model = AutoModelForCausalLM.from_pretrained(model_path, low_cpu_mem_usage=True)
tokenizer = AutoTokenizer.from_pretrained(model_path)

# 2、加载PeftModel
p_model = PeftModel.from_pretrained(model, model_id="./chatbot/checkpoint-500/")

# 3、模型合并
merge_model = p_model.merge_and_unload()

# 4、完整模型保存,此时大小就很大了,下次加载时候可以用AutoModelForCausalLM直接加载
merge_model.save_pretrained("./chatbot/merge_model")

2 AdaLoRA

2.1 AdaLoRA简介

  • 论文地址:ADAPTIVE BUDGET ALLOCATION FOR PARAMETER EFFICIENT FINE-TUNING(23.03)

  • LoRA可以达到与完全微调几乎相当的性能,但是也存在一些问题。

    • LoRA需要预先指定每个增量矩阵的本征秩 r 相同,忽略了在微调预训练模型时,权重矩阵的重要性在不同模块和层之间存在显著差异
    • 并且只训练了Attention,没有训练FFN,事实上FFN更重要。
  • 如下图a所示,将可微调参数全部放在FFN的效果要好于放在attention矩阵中的效果;如下图b所示,同时微调高层参数的效果会比微调底层参数的效果更好。因此,作者提出了AdaLoRA,它根据权重矩阵的重要性得分,在权重矩阵之间自适应地分配参数预算。

在这里插入图片描述

  • AdaLORA主要包含两个模块:

    • (i) SVD形式参数更新(SVD-based adaptation):直接将增量矩阵Δ参数化为SVD的形式,避免了在训练过程中进行SVD计算带来的资源消耗;

    在这里插入图片描述

    • (ii) 基于重要程度的参数分配(Importance-aware rank allocation): 裁剪一些冗余的奇异值。

      具体原理可以参考:AdaLoRA(Adaptive LoRA)详解

2.2 AdaLoRA轻量微调bloom模型

  • 这里我们没有分析AdaLoRA的源码,直接进行轻量微调,有兴趣的可以分析下源码。

  • 同样,我们只需要在加载原模型后、配置训练器前加peft的代码即可。

from peft import get_peft_model, TaskType, AdaLoraConfig

config = AdaLoraConfig(task_type=TaskType.CAUSAL_LM
                            , r=8
                            , lora_alpha=8
                            , lora_dropout=0
                            , target_modules=["query_key_value"]
                            )


model = get_peft_model(model, config)

# 打印可训练参数
model.print_trainable_parameters()

trainable params: 1,179,936 || all params: 346,948,920 || trainable%: 0.3400892557901607
  • 配置训练器、模型训练及推理和参数高效微调PEFT(一)快速入门BitFit、Prompt Tuning、Prefix Tuning中2.1一样。
  • 显存消耗情况:
(base) root@autodl-container-adbc11ae52-f2ebff02:~/autodl-tmp/transformers-code/03-PEFT# nvidia-smi  
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 525.89.02    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:41:00.0 Off |                  N/A |
| 33%   54C    P2   119W / 250W |   2816MiB / 11264MiB |     32%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/664534.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML静态网页成品作业(HTML+CSS)——努比亚手机商城介绍网页(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

【ANdroid】WEb服务搭建华为云

访问本机地址&#xff1a;tomcaT(在设置-网络属性查找本机地址的ipv4 注册华为云账号——IOT 网络地址&#xff1a;8080&#xff08;访问地址&#xff09;要在newsStudy修改为本机地址的地址 注册成功付费后&#xff0c;打开cloudSHEll进入linux命令台 保存文件在home目录下…

百度地图2

覆盖物 叠加层 添加叠加层 GroundOverlay(bounds: Bounds, opts: GroundOverlayOptions):地图上的地面叠加层。 Bounds(sw: Point, ne: Point):表示地理坐标的矩形区域。sw表示矩形区域的西南角&#xff0c;参数ne表示矩形区域的东北角。 GroundOverlayOptions&#xff1a…

一文简述「低代码」到底是什么?

低代码是什么&#xff1f;低代码原理是什么&#xff1f;低代码的组成要素有哪些&#xff1f;低代码应用场景有哪些&#xff1f;低代码的优势是什么&#xff1f;低代码开发平台与传统开发方法的区别&#xff1f;本文是本人和团队从业十年来的经验结晶&#xff0c;全文3000&#…

ChatTTS,语气韵律媲美真人的开源TTS模型,文字转语音界的新魁首,对标微软Azure-tts

前两天 2noise 团队开源了ChatTTS项目&#xff0c;并且释出了相关的音色模型权重&#xff0c;效果确实非常惊艳&#xff0c;让人一听难忘&#xff0c;即使摆在微软的商业级项目Azure-tts面前&#xff0c;也是毫不逊色的。 ChatTTS是专门为对话场景设计的文本转语音模型&#x…

Python中的 Lambda 函数

大家好&#xff0c;在 Python 编程的世界里&#xff0c;有一种功能强大却不常被提及的工具&#xff0c;它就是 Lambda 函数。这种匿名函数在 Python 中拥有着令人惊叹的灵活性和简洁性&#xff0c;却常常被许多开发者忽视或者只是将其当作一种附加功能。Lambda 函数的引入&…

FPGA DMA IP核使用指南

摘要 本文旨在介绍FPGA中DMA(Direct Memory Access)IP核的使用,包括其基本框架、测试代码编写以及仿真波形的分析。DMA是一种允许外围设备直接与内存进行数据交换的技术,无需CPU的介入,从而提高了数据传输的效率。 1. 引言 在现代FPGA设计中,DMA IP核因其…

(1+X)Java程序设计高级(一)

Throwable&#xff1a;异常的基类&#xff0c;所有异常都继承自 java.lang.Throwable 类&#xff0c;Throwable 类有两个直接子类&#xff1a;Error 类和 Exception 类。Error&#xff1a;是 Java 应用程序本身无法恢复的严重错误&#xff0c;应用程序不需要捕获、处理这些严重…

Java基础语法规范

语法规范 public class HelloWorld{ //类名&#xff1a; 1. 首字母要大写 2. 源文件名与类名相同// 单行注释/* 多行注释除这两个之外还有文档注释。不重要* /public static void main (String[] args){ /* 1. main()⽅法是类体中的主⽅法&#xff0c;该⽅法从{开始到}结束…

OpenEuler 的安装过程记录

一、下载openEuler镜像 1.2 打开官网&#xff0c;选择openEuler23.09 1.3 选择架构、场景以及软件包类型 初次使用的话基本上都是先安装虚拟机&#xff0c;我们大部分主机都是x86_64架构&#xff0c;场景的话就选服务器&#xff0c;软件版类型选择标准版&#xff0c;可以安装图…

两数之和-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第76讲。 两数之和&#xf…

基恩士激光 速度 曝光等关系

一、基恩士 CtrlN 二、速度设置 计算扫描速度 曝光时间&#xff1a; 1:1 相机点间隔是0.025 &#xff0c;我们要扫描的图像也是1&#xff1a;1的话&#xff0c;速度可以为 采样周期我们设定为3K&#xff0c;假如我们的7000行就够了 速度V0.025&#xff08;线间隔&#xff0…

【python】OpenCV—Color Detection

学习来自 如何使用 OpenCV Python 检测颜色 import cv2 import numpy as npdef red_hsv(img, saveFalse):lower_hsv1 np.array([0, 175, 20])higher_hsv1 np.array([10, 255, 255])lower_hsv2 np.array([170, 175, 20])higer_hsv2 np.array([10, 255, 255])mask1 cv2.inR…

小家电增速超预期!赛盈分销谈市场发展机会,助力企业开拓新商机!

在家庭和商业场景的高需求下&#xff0c;小家电又成为了海外消费新宠。 Statista的数据显示&#xff0c;2023年全球小家电的市场规模达到了2430亿美元&#xff0c;预计未来的4年里市场年复合增长率为4.65%&#xff0c;到2028年市场规模将增长至3050亿美元。 特别是欧美和东南亚…

小短片创作-理论知识(四)

1、PBR材质基础参数 1.PBR材质的特征&#xff1a;BaseColor&#xff0c;Roughness&#xff0c;Metallic&#xff0c;Normal&#xff0c;Specular 2.BaseColor&#xff08;Albedo&#xff09;&#xff1a;不包含光照信息 3.Roughness&#xff08;粗糙度&#xff09;&#xff…

Ubuntu (18.04) _Mysql (8.0.X)设置密码强度

首先 查看是否有密码强度插件&#xff1a; SHOW PLUGINS; 如果没有&#xff0c;则安装 install plugin validate_password soname validate_password.so; 再次查看,会看到密码强度插件已开 其次 查看密码强度具体配置 show variables like validate_password%; validate…

JVM思维导图

帮助我们快速整理和总结JVM相关知识&#xff0c;有结构化认识和整体的思维模型 JVM相关详细知识和面试题

农业大模型:关键技术、应用分析与发展方向

&#xff3b;目的/意义&#xff3d; 近年来&#xff0c;人工智能在农业领域的应用取得了显著进展&#xff0c;但仍面临诸如模型数据收集标记困难、模型泛化能力弱等挑战。大模型技术作为近期人工智能领域新的热点技术&#xff0c;已在多个行业的垂直领域中展现出了良好性能&…

【EFK日志系统】在kibana操作索引模板、生命周期、管道等

kibana界面设置 管道生命周期索引模板索引模式注意事项 之前已经搭建好了es集群、es-head信息面板、kibana、filebeat和metricbeat&#xff0c;但是其中的索引模板等信息你在kibana界面暂时看不到 接下来我们设置索引模式、索引模板、生命周期、管道限制等&#xff0c;简单写一…

商用未来何时来?软银揭示量子计算商业应用现状

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨沛贤/浪味仙 排版丨沛贤 深度好文&#xff1a;3000字丨10分钟阅读 摘要&#xff1a;软银&#xff08;SoftBank&#xff09;先进技术研究所正在积极推进量子计算商业应用&#xff0c;借助与…