华为开源自研AI框架昇思MindSpore应用案例:在ResNet-50网络上应用二阶优化实践

news2024/11/18 21:34:03

常见的优化算法可分为一阶优化算法和二阶优化算法。经典的一阶优化算法如SGD等,计算量小、计算速度快,但是收敛的速度慢,所需的迭代次数多。而二阶优化算法使用目标函数的二阶导数来加速收敛,能更快地收敛到模型最优值,所需要的迭代次数少,但由于二阶优化算法过高的计算成本,导致其总体执行时间仍然慢于一阶,故目前在深度神经网络训练中二阶优化算法的应用并不普遍。二阶优化算法的主要计算成本在于二阶信息矩阵(Hessian矩阵、FIM矩阵等)的求逆运算,时间复杂度约为𝑂(𝑛3)。

MindSpore开发团队在现有的自然梯度算法的基础上,对FIM矩阵采用近似、切分等优化加速手段,极大的降低了逆矩阵的计算复杂度,开发出了可用的二阶优化器THOR。使用8块Atlas训练系列产品,THOR可以在72min内完成ResNet50-v1.5网络和ImageNet数据集的训练,相比于SGD+Momentum速度提升了近一倍。

本篇教程将主要介绍如何在Atlas训练系列产品以及GPU上,使用MindSpore提供的二阶优化器THOR训练ResNet50-v1.5网络和ImageNet数据集。

如果你对MindSpore感兴趣,可以关注昇思MindSpore社区

在这里插入图片描述

在这里插入图片描述

一、环境准备

1.进入ModelArts官网

云平台帮助用户快速创建和部署模型,管理全周期AI工作流,选择下面的云平台以开始使用昇思MindSpore,获取安装命令,安装MindSpore2.0.0-alpha版本,可以在昇思教程中进入ModelArts官网

在这里插入图片描述

选择下方CodeLab立即体验

在这里插入图片描述

等待环境搭建完成

在这里插入图片描述

2.使用CodeLab体验Notebook实例

下载NoteBook样例代码

git clone https://gitee.com/mindspore/models.git

选择ModelArts terminal

在official/cv/ResNet目录下

选择Kernel环境

在这里插入图片描述

切换至GPU环境,切换成第一个限时免费

在这里插入图片描述

进入昇思MindSpore官网,点击上方的安装

在这里插入图片描述

获取安装命令

在这里插入图片描述

回到Notebook中,在第一块代码前加入命令
在这里插入图片描述

conda update -n base -c defaults conda

在这里插入图片描述

安装MindSpore 2.0 GPU版本

conda install mindspore=2.0.0a0 -c mindspore -c conda-forge

在这里插入图片描述

安装mindvision

pip install mindvision

在这里插入图片描述

安装下载download

pip install download

在这里插入图片描述

二、案例实现

下载完整示例代码:Resnet。

示例代码目录结构

├── resnet
    ├── README.md
    ├── scripts
        ├── run_distribute_train.sh         # launch distributed training for Atlas training series
        ├── run_eval.sh                     # launch inference for Atlas training series
        ├── run_distribute_train_gpu.sh     # launch distributed training for GPU
        ├── run_eval_gpu.sh                 # launch inference for GPU
    ├── src
        ├── dataset.py                      # data preprocessing
        ├── CrossEntropySmooth.py           # CrossEntropy loss function
        ├── lr_generator.py                 # generate learning rate for every step
        ├── resnet.py                       # ResNet50 backbone
        ├── model_utils
            ├── config.py                   # parameter configuration
    ├── eval.py                             # infer script
    ├── train.py                            # train script

整体执行流程如下:

  1. 准备ImageNet数据集,处理需要的数据集;

  2. 定义ResNet50网络;

  3. 定义损失函数和THOR优化器;

  4. 加载数据集并进行训练,训练完成后,查看结果及保存模型文件;

  5. 加载保存的模型,进行推理。

准备环节

实践前,确保已经正确安装MindSpore。如果没有,可以通过MindSpore安装页面安装MindSpore。

准备数据集

下载完整的ImageNet2012数据集,将数据集解压分别存放到本地工作区的ImageNet2012/ilsvrcImageNet2012/ilsvrc_eval路径下。

目录结构如下:

└─ImageNet2012
    ├─ilsvrc
    │      n03676483
    │      n04067472
    │      n01622779
    │      ......
    └─ilsvrc_eval
    │      n03018349
    │      n02504013
    │      n07871810
    │      ......

配置分布式环境变量

Atlas训练系列产品

Atlas训练系列产品的分布式环境变量配置参考rank table启动方式。

GPU

GPU的分布式环境配置参考mpirun启动方式。

加载处理数据集

分布式训练时,通过并行的方式加载数据集,同时通过MindSpore提供的数据增强接口对数据集进行处理。加载处理数据集的脚本在源码的src/dataset.py脚本中。

import os
import mindspore as ms
import mindspore.dataset as ds
import mindspore.dataset.vision as vision
import mindspore.dataset.transforms as transforms
from mindspore.communication import init, get_rank, get_group_size


def create_dataset2(dataset_path, do_train, repeat_num=1, batch_size=32, target="Ascend", distribute=False,
                    enable_cache=False, cache_session_id=None):
    """
    Create a training or evaluation ImageNet2012 dataset for ResNet50.

    Args:
        dataset_path(string): the path of dataset.
        do_train(bool): whether the dataset is used for training or evaluation.
        repeat_num(int): the repeat times of dataset. Default: 1
        batch_size(int): the batch size of dataset. Default: 32
        target(str): the device target. Default: Ascend
        distribute(bool): data for distribute or not. Default: False
        enable_cache(bool): whether tensor caching service is used for evaluation. Default: False
        cache_session_id(int): if enable_cache is set, cache session_id need to be provided. Default: None

    Returns:
        dataset
    """
    if target == "Ascend":
        device_num, rank_id = _get_rank_info()
    else:
        if distribute:
            init()
            rank_id = get_rank()
            device_num = get_group_size()
        else:
            device_num = 1

    if device_num == 1:
        data_set = ds.ImageFolderDataset(dataset_path, num_parallel_workers=8, shuffle=True)
    else:
        data_set = ds.ImageFolderDataset(dataset_path, num_parallel_workers=8, shuffle=True,
                                         num_shards=device_num, shard_id=rank_id)

    image_size = 224
    mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]
    std = [0.229 * 255, 0.224 * 255, 0.225 * 255]

    # define map operations
    if do_train:
        trans = [
            vision.RandomCropDecodeResize(image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),
            vision.RandomHorizontalFlip(prob=0.5),
            vision.Normalize(mean=mean, std=std),
            vision.HWC2CHW()
        ]
    else:
        trans = [
            vision.Decode(),
            vision.Resize(256),
            vision.CenterCrop(image_size),
            vision.Normalize(mean=mean, std=std),
            vision.HWC2CHW()
        ]

    type_cast_op = transforms.TypeCast(ms.int32)

    data_set = data_set.map(operations=trans, input_columns="image", num_parallel_workers=8)
    # only enable cache for eval
    if do_train:
        enable_cache = False
    if enable_cache:
        if not cache_session_id:
            raise ValueError("A cache session_id must be provided to use cache.")
        eval_cache = ds.DatasetCache(session_id=int(cache_session_id), size=0)
        data_set = data_set.map(operations=type_cast_op, input_columns="label", num_parallel_workers=8,
                                cache=eval_cache)
    else:
        data_set = data_set.map(operations=type_cast_op, input_columns="label", num_parallel_workers=8)

    # apply batch operations
    data_set = data_set.batch(batch_size, drop_remainder=True)

    # apply dataset repeat operation
    data_set = data_set.repeat(repeat_num)

    return data_set

MindSpore支持进行多种数据处理和增强的操作,各种操作往往组合使用,具体可以参考数据处理和数据增强章节。

定义网络

本示例中使用的网络模型为ResNet50-v1.5,定义ResNet50网络。

网络构建完成以后,在__main__函数中调用定义好的ResNet50:

...
from src.resnet import resnet50 as resnet
...
if __name__ == "__main__":
    ...
    # define net
    net = resnet(class_num=config.class_num)
    ...

定义损失函数及THOR优化器

定义损失函数

MindSpore支持的损失函数有SoftmaxCrossEntropyWithLogitsL1LossMSELoss等。THOR优化器需要使用SoftmaxCrossEntropyWithLogits损失函数。

损失函数的实现步骤在src/CrossEntropySmooth.py脚本中。这里使用了深度网络模型训练中的一个常用trick:label smoothing,通过对真实标签做平滑处理,提高模型对分类错误标签的容忍度,从而可以增加模型的泛化能力。

class CrossEntropySmooth(LossBase):
    """CrossEntropy"""
    def __init__(self, sparse=True, reduction='mean', smooth_factor=0., num_classes=1000):
        super(CrossEntropySmooth, self).__init__()
        self.onehot = ops.OneHot()
        self.sparse = sparse
        self.on_value = ms.Tensor(1.0 - smooth_factor, ms.float32)
        self.off_value = ms.Tensor(1.0 * smooth_factor / (num_classes - 1), ms.float32)
        self.ce = nn.SoftmaxCrossEntropyWithLogits(reduction=reduction)

    def construct(self, logit, label):
        if self.sparse:
            label = self.onehot(label, ops.shape(logit)[1], self.on_value, self.off_value)
        loss = self.ce(logit, label)
        return loss

__main__函数中调用定义好的损失函数:

...
from src.CrossEntropySmooth import CrossEntropySmooth
...
if __name__ == "__main__":
    ...
    # define the loss function
    if not config.use_label_smooth:
        config.label_smooth_factor = 0.0
    loss = CrossEntropySmooth(sparse=True, reduction="mean",
                              smooth_factor=config.label_smooth_factor, num_classes=config.class_num)
    ...

定义优化器

THOR优化器的参数更新公式如下:

𝜃𝑡+1=𝜃𝑡+𝛼𝐹−1∇𝐸

参数更新公式中各参数的含义如下:

  • 𝜃:网络中的可训参数;

  • 𝑡:迭代次数;

  • 𝛼:学习率值,参数的更新步长;

  • 𝐹−1:FIM矩阵,在网络中计算获得;

  • ∇𝐸:一阶梯度值。

从参数更新公式中可以看出,THOR优化器需要额外计算的是每一层的FIM矩阵。FIM矩阵可以对每一层参数更新的步长和方向进行自适应的调整,加速收敛的同时可以降低调参的复杂度。

在调用MindSpore封装的二阶优化器THOR时,优化器会自动调用转换接口,把之前定义好的ResNet50网络中的Conv2d层和Dense层分别转换成对应的Conv2dThor和DenseThor。 而在Conv2dThor和DenseThor中可以完成二阶信息矩阵的计算和存储。

THOR优化器转换前后的网络backbone一致,网络参数保持不变。

在训练主脚本中调用THOR优化器:

...
from mindspore.nn import thor
...
if __name__ == "__main__":
    ...
    # learning rate setting and damping setting
    from src.lr_generator import get_thor_lr, get_thor_damping
    lr = get_thor_lr(0, config.lr_init, config.lr_decay, config.lr_end_epoch, step_size, decay_epochs=39)
    damping = get_thor_damping(0, config.damping_init, config.damping_decay, 70, step_size)
    # define the optimizer
    split_indices = [26, 53]
    opt = thor(net, ms.Tensor(lr), ms.Tensor(damping), config.momentum, config.weight_decay, config.loss_scale,
               config.batch_size, split_indices=split_indices, frequency=config.frequency)
    ...

训练网络

配置模型保存

MindSpore提供了callback机制,可以在训练过程中执行自定义逻辑,这里使用框架提供的ModelCheckpoint函数。 ModelCheckpoint可以保存网络模型和参数,以便进行后续的fine-tuning操作。 TimeMonitorLossMonitor是MindSpore官方提供的callback函数,可以分别用于监控训练过程中单步迭代时间和loss值的变化。

...
import mindspore as ms
from mindspore.train import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor
...
if __name__ == "__main__":
    ...
    # define callbacks
    time_cb = TimeMonitor(data_size=step_size)
    loss_cb = LossMonitor()
    cb = [time_cb, loss_cb]
    if config.save_checkpoint:
        config_ck = CheckpointConfig(save_checkpoint_steps=config.save_checkpoint_epochs * step_size,
                                     keep_checkpoint_max=config.keep_checkpoint_max)
        ckpt_cb = ModelCheckpoint(prefix="resnet", directory=ckpt_save_dir, config=config_ck)
        cb += [ckpt_cb]
    ...

配置训练网络

通过MindSpore提供的model.train接口可以方便地进行网络的训练。THOR优化器通过降低二阶矩阵更新频率,来减少计算量,提升计算速度,故重新定义一个ModelThor类,继承MindSpore提供的Model类。在ModelThor类中获取THOR的二阶矩阵更新频率控制参数,用户可以通过调整该参数,优化整体的性能。 MindSpore提供Model类向ModelThor类的一键转换接口。

...
import mindspore as ms
from mindspore import amp
from mindspore.train import Model, ConvertModelUtils
...

if __name__ == "__main__":
    ...
    loss_scale = amp.FixedLossScaleManager(config.loss_scale, drop_overflow_update=False)
    model = Model(net, loss_fn=loss, optimizer=opt, loss_scale_manager=loss_scale, metrics=metrics,
                  amp_level="O2", keep_batchnorm_fp32=False, eval_network=dist_eval_network)
    if cfg.optimizer == "Thor":
        model = ConvertModelUtils().convert_to_thor_model(model=model, network=net, loss_fn=loss, optimizer=opt,
                                                          loss_scale_manager=loss_scale, metrics={'acc'},
                                                          amp_level="O2", keep_batchnorm_fp32=False)  
    ...

运行脚本

训练脚本定义完成之后,调scripts目录下的shell脚本,启动分布式训练进程。

Atlas训练系列产品

目前MindSpore分布式在Ascend上执行采用单卡单进程运行方式,即每张卡上运行1个进程,进程数量与使用的卡的数量一致。进程均放在后台执行,每个进程创建1个目录,目录名称为train_paralleldevice_id,用来保存日志信息,算子编译信息以及训练的checkpoint文件。下面以使用8张卡的分布式训练脚本为例,演示如何运行脚本。

使用以下命令运行脚本:

bash run_distribute_train.sh <RANK_TABLE_FILE> <DATASET_PATH> [CONFIG_PATH]

脚本需要传入变量RANK_TABLE_FILEDATASET_PATHCONFIG_PATH,其中:

  • RANK_TABLE_FILE:组网信息文件的路径。(rank table文件的生成,参考HCCL_TOOL)

  • DATASET_PATH:训练数据集路径。

  • CONFIG_PATH:配置文件路径。

其余环境变量请参考安装教程中的配置项。

训练过程中loss打印示例如下:

...
epoch: 1 step: 5004, loss is 4.4182425
epoch: 2 step: 5004, loss is 3.740064
epoch: 3 step: 5004, loss is 4.0546017
epoch: 4 step: 5004, loss is 3.7598825
epoch: 5 step: 5004, loss is 3.3744206
...
epoch: 40 step: 5004, loss is 1.6907625
epoch: 41 step: 5004, loss is 1.8217756
epoch: 42 step: 5004, loss is 1.6453942
...

训练完后,每张卡训练产生的checkpoint文件保存在各自训练目录下,device_0产生的checkpoint文件示例如下:

└─train_parallel0
    ├─ckpt_0
        ├─resnet-1_5004.ckpt
        ├─resnet-2_5004.ckpt
        │      ......
        ├─resnet-42_5004.ckpt
        │      ......

其中, *.ckpt:指保存的模型参数文件。checkpoint文件名称具体含义:网络名称-epoch数_step数.ckpt。

GPU

在GPU硬件平台上,MindSpore采用OpenMPI的mpirun进行分布式训练,进程创建1个目录,目录名称为train_parallel,用来保存日志信息和训练的checkpoint文件。下面以使用8张卡的分布式训练脚本为例,演示如何运行脚本。

使用以下命令运行脚本:

bash run_distribute_train_gpu.sh <DATASET_PATH> <CONFIG_PATH>

脚本需要传入变量DATASET_PATHCONFIG_PATH,其中:

  • DATASET_PATH:训练数据集路径。

  • CONFIG_PATH:配置文件路径。

在GPU训练时,无需设置DEVICE_ID环境变量,因此在主训练脚本中不需要调用int(os.getenv('DEVICE_ID'))来获取卡的物理序号,同时context中也无需传入device_id。我们需要将device_target设置为GPU,并需要调用init()来使能NCCL。

训练过程中loss打印示例如下:

...
epoch: 1 step: 5004, loss is 4.2546034
epoch: 2 step: 5004, loss is 4.0819564
epoch: 3 step: 5004, loss is 3.7005644
epoch: 4 step: 5004, loss is 3.2668946
epoch: 5 step: 5004, loss is 3.023509
...
epoch: 36 step: 5004, loss is 1.645802
...

训练完后,保存的模型文件示例如下:

└─train_parallel
    ├─ckpt_0
        ├─resnet-1_5004.ckpt
        ├─resnet-2_5004.ckpt
        │      ......
        ├─resnet-36_5004.ckpt
        │      ......
    ......
    ├─ckpt_7
        ├─resnet-1_5004.ckpt
        ├─resnet-2_5004.ckpt
        │      ......
        ├─resnet-36_5004.ckpt
        │      ......

模型推理

使用训练过程中保存的checkpoint文件进行推理,验证模型的泛化能力。首先通过load_checkpoint接口加载模型文件,然后调用Modeleval接口对输入图片类别作出预测,再与输入图片的真实类别做比较,得出最终的预测精度值。

定义推理网络

  1. 使用load_checkpoint接口加载模型文件。

  2. 使用model.eval接口读入测试数据集,进行推理。

  3. 计算得出预测精度值。

...
import mindspore as ms
from mindspore.train import Model
...

if __name__ == "__main__":
    ...
    # define net
    net = resnet(class_num=config.class_num)

    # load checkpoint
    param_dict = ms.load_checkpoint(args_opt.checkpoint_path)
    ms.load_param_into_net(net, param_dict)
    net.set_train(False)

    # define loss
    if args_opt.dataset == "imagenet2012":
        if not config.use_label_smooth:
            config.label_smooth_factor = 0.0
        loss = CrossEntropySmooth(sparse=True, reduction='mean',
                                  smooth_factor=config.label_smooth_factor, num_classes=config.class_num)
    else:
        loss = SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')

    # define model
    model = Model(net, loss_fn=loss, metrics={'top_1_accuracy', 'top_5_accuracy'})

    # eval model
    res = model.eval(dataset)
    print("result:", res, "ckpt=", args_opt.checkpoint_path)
    ...

执行推理

推理网络定义完成之后,调用scripts目录下的shell脚本,进行推理。

Atlas训练系列产品

在Atlas训练系列产品平台上,推理的执行命令如下:

bash run_eval.sh <DATASET_PATH> <CHECKPOINT_PATH> <CONFIG_PATH>

脚本需要传入变量DATASET_PATHCHECKPOINT_PATH<CONFIG_PATH>,其中:

  • DATASET_PATH:推理数据集路径。

  • CHECKPOINT_PATH:保存的checkpoint路径。

  • CONFIG_PATH:配置文件路径。

目前推理使用的是单卡(默认device 0)进行推理,推理的结果如下:

result: {'top_5_accuracy': 0.9295574583866837, 'top_1_accuracy': 0.761443661971831} ckpt=train_parallel0/resnet-42_5004.ckpt
  • top_5_accuracy:对于一个输入图片,如果预测概率排名前五的标签中包含真实标签,即认为分类正确;

  • top_1_accuracy:对于一个输入图片,如果预测概率最大的标签与真实标签相同,即认为分类正确。

GPU

在GPU硬件平台上,推理的执行命令如下:

  bash run_eval_gpu.sh <DATASET_PATH> <CHECKPOINT_PATH> <CONFIG_PATH>

脚本需要传入变量DATASET_PATHCHECKPOINT_PATHCONFIG_PATH,其中:

  • DATASET_PATH:推理数据集路径。

  • CHECKPOINT_PATH:保存的checkpoint路径。

  • CONFIG_PATH:配置文件路径。

推理的结果如下:

result: {'top_5_accuracy': 0.9287972151088348, 'top_1_accuracy': 0.7597031049935979} ckpt=train_parallel/resnet-36_5

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TCP的滑动窗口机制和流量控制

目录 滑动窗口 流量控制 拥塞控制 滑动窗口 TCP除了保证可靠性之外&#xff0c;也希望能够尽可能高效的完成数据传输。滑动窗口就是一种提高效率的机制。以下是不引入滑动窗口的数据传输过程&#xff1a; 可以看到&#xff0c;主机A这边每次收到一个ACK才发送下一个数据。这…

接口、会话控制

文章目录 接口介绍RESTful APIjson-server接口测试工具apipost公共参数和文档功能 会话控制cookie介绍和使用运行流程浏览器中操作Cookieexpress中cookie操作 Sessionsession运行流程&#xff1a;session中间件配置session 和 cookie 的区别CSRF跨站请求伪造 tokenJWT介绍与演示…

数据新探:用Python挖掘互联网的隐藏宝藏

Hello&#xff0c;我是你们的阿佑&#xff0c;今天给大家上的菜是——数据存储&#xff01;听起来枯燥无味&#xff1f;错了&#xff01;阿佑将带你重新认识数据存储的艺术。就像为珍贵的艺术品寻找完美的展览馆&#xff0c;为你的数据选择合适的存储方式同样重要&#xff01; …

2022-1990年 各省碳排放Co2数据集(含数据及参考文献)

碳排放是指人类活动产生的二氧化碳&#xff08;CO2&#xff09;等温室气体释放到大气中的过程。通过划分排放源的范围以避免重复计算的思想&#xff0c;由世界资源研究所在关于企业温室气体排放清单编制的指南中首次提出。城市碳排放核算边界界定借鉴该思想&#xff0c;可分为3…

Web开发三层架构

##Controller Service Dao(mapper) 软件设计&#xff1a;高内聚 低耦合 Controller 调用Service&#xff0c; Service调用 DAO 模块之间耦合 如果要从EmpServiceA切换到EmpServiceB&#xff0c;Controller代码也要修改 new EmpServiceB 分层接耦 容器中放EmpServiceA&am…

(深度估计学习)Win11复现DepthFM

目录 1. 系统配置2. 拉取代码&#xff0c;配置环境3.开始深度预测4.运行结果 论文链接&#xff1a;https://depthfm.github.io/ 讲解链接&#xff1a;https://www.php.cn/faq/734404.html 1. 系统配置 本人系统&#xff1a;Win11 CUDA12.2 python3.11.5 这里附上几个CUDA安装链…

Linux第四节--常见的指令介绍集合(持续更新中)

点赞关注不迷路&#xff01;本节涉及初识Linux第四节&#xff0c;主要为常见的几条指令介绍。 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1f44d;&#x1f3fb; 收藏 ✨ 加关注&#x1f440; 期待与你共同进步! 1. more指令 语法&#xff1a;more [选项][文件]…

【数据可视化01】matplotlib实例介绍4之六边形分箱图

目录 一、引言二、实例介绍 一、引言 hexbin是一个二维直方图&#xff0c;其中箱子是六边形&#xff0c;颜色表示每个箱子内的数据点数。 二、实例介绍 import matplotlib.pyplot as plt import numpy as np# Fixing random state for reproducibility np.random.seed(19680…

umi搭建react项目

UMI 是一个基于 React 的可扩展企业级前端应用框架&#xff0c;提供路由、状态管理、构建和部署等功能&#xff0c;可以帮助开发者快速构建复杂的单页面应用&#xff08;SPA&#xff09;和多页面应用&#xff08;MPA&#xff09;。它与 React 的关系是&#xff0c;UMI 构建在 R…

draw.io 网页版二次开发(1):源码下载和环境搭建

目录 一 说明 二 源码地址以及下载 三 开发环境搭建 1. 前端工程地址 2. 配置开发环境 &#xff08;1&#xff09;安装 node.js &#xff08;2&#xff09;安装 serve 服务器 3. 运行 四 最后 一 说明 应公司项目要求&#xff0c;需要对draw.io进行二次开发&…

算法提高之加成序列

算法提高之加成序列 核心思想&#xff1a;迭代加深 dfs 从上往下逐渐增大depth 这样下面没有用的方案就不用遍历了 #include <iostream>#include <cstring>#include <algorithm>using namespace std;const int N 110;int n;int path[N];//当前求哪个位置…

2.1.2 事件驱动reactor的原理与实现

LINUX 精通 2 day14 20240513 day15 20240514 算法刷题&#xff1a;2维前缀和&#xff0c;一二维差分 耗时 135min 习题课 4h 课程补20240425 耗时&#xff1a;4h 课程链接地址 回顾 怎么学0voice课网络io——一请求一线程&#xff0c;一个client一个连接再accpet分配io f…

考研数学|李林《880》做不动,怎么办!?看这一篇!

在考研数学的备考过程中&#xff0c;遇到难题是很常见的情况&#xff0c;尤其是当你尝试解决李林880习题集中的问题时。他以其难度和深度著称&#xff0c;旨在帮助考生深入理解数学分析的复杂概念。 如果你在解题过程中感到困难&#xff0c;这并不是你个人的问题&#xff0c;而…

数据库系统概论(超详解!!!)第八节 数据库设计

1.数据库设计概述 数据库设计是指对于一个给定的应用环境&#xff0c;构造&#xff08;设计&#xff09;优化的数据库逻辑模式和物理结构&#xff0c;并据此建立数据库及其应用系统&#xff0c;使之能够有效地存储和管理数据&#xff0c;满足各种用户的应用需求&#xff0c;包…

【LLM第五篇】名词解释:prompt

1.是什么 提示工程&#xff08;Prompt Engineering&#xff09;是一门较新的学科&#xff0c;关注提示词开发和优化&#xff0c;帮助用户将大语言模型&#xff08;Large Language Model, LLM&#xff09;用于各场景和研究领域。 掌握了提示工程相关技能将有助于用户更好地了解…

Prosys OPC UA Simulation Server工程文件备份方法

Prosys OPC UA Simulation Server是一款免费的OPC UA服务器仿真软件&#xff0c;具体的使用和下载参考官网&#xff1a; Prosys OPC - OPC UA Simulation Server Downloads 他的免费版本不提供工程文件的备份、导入导出功能&#xff0c;每次退出时保存。如果需要工程备份&a…

宇宙(科普)

宇宙&#xff08;Universe&#xff09;在物理意义上被定义为所有的空间和时间&#xff08;统称为时空&#xff09;及其内涵&#xff0c;包括各种形式的所有能量&#xff0c;比如电磁辐射、普通物质、暗物质、暗能量等&#xff0c;其中普通物质包括行星、卫星、恒星、星系、星系…

基于安装包安装数据库时出现的问题分析及总结

数据库在数据初始化后并不会出现错误&#xff0c;这个时候在启动数据库时会出现启动不成功&#xff0c;不知道问题是什么要学会通过查看日志发现问题&#xff0c;日志就在Data文件夹下。 错误类型1 数据库在初始化后数据库启动不起来 原因&#xff1a;可能是配置文件my.ini一些…

【SQL每日一练】获取PADS公司用户名称和各职业总数并根据格式输出

文章目录 题目一、解析二、题解1.MySQL 题目 生成以下两个结果集&#xff1a; 1、查询 OCCUPATIONS 表中所有名字&#xff0c;紧跟每个职业的第一个字母作为括号&#xff08;即&#xff1a;括在括号中&#xff09;&#xff0c;并按名字顺序排序。例如&#xff1a;AnActorName…

2024成都现代职业教育及装备展6月1日举办 免费参观

2024成都现代职业教育及装备展6月1日举办 免费参观 同期举办&#xff1a;中国西部职业教育产教融合高峰论坛 主办单位&#xff1a; 中国西部教体融合博览会组委会 承办单位&#xff1a;重庆港华展览有限公司 博览会主题&#xff1a;责任教育 职教兴邦 组委会&#xff1a;…