[模型部署] 1. 模型导出
👋 你好!这里有实用干货与深度分享✨✨ 若有帮助,欢迎:
👍 点赞 | ⭐ 收藏 | 💬 评论 | ➕ 关注 ,解锁更多精彩!
📁 收藏专栏即可第一时间获取最新推送🔔。
📖后续我将持续带来更多优质内容,期待与你一同探索知识,携手前行,共同进步🚀。
模型导出
本文介绍如何将深度学习模型导出为不同的部署格式,包括ONNX、TorchScript等,并对各种格式的优缺点和最佳实践进行总结,帮助你高效完成模型部署准备。
1. 导出格式对比
格式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
ONNX | - 跨平台跨框架 - 生态丰富 - 标准统一 - 广泛支持 | - 可能存在算子兼容问题 - 部分高级特性支持有限 | - 跨平台部署 - 使用标准推理引擎 - 需要广泛兼容性 |
TorchScript | - 与PyTorch无缝集成 - 支持动态图结构 - 调试方便 - 性能优化 | - 仅限PyTorch生态 - 文件体积较大 | - PyTorch生产环境 - 需要动态特性 - 性能要求高 |
TensorRT | - 极致优化性能 - 支持GPU加速 - 低延迟推理 | - 仅支持NVIDIA GPU - 配置复杂 | - 高性能推理场景 - 实时应用 - 边缘计算 |
TensorFlow SavedModel | - TensorFlow生态完整支持 - 部署便捷 | - 跨框架兼容性差 | - TensorFlow生产环境 |
2. ONNX格式导出
2.1 基本导出
ONNX格式适用于跨平台部署,支持多种推理引擎(如ONNXRuntime、TensorRT、OpenVINO等)。
import torch
import torch.onnxdef export_to_onnx(model, input_shape, save_path):# 设置模型为评估模式model.eval()# 创建示例输入dummy_input = torch.randn(input_shape)# 导出模型torch.onnx.export(model, # 要导出的模型dummy_input, # 模型输入save_path, # 保存路径export_params=True, # 导出模型参数opset_version=11, # ONNX算子集版本do_constant_folding=True, # 常量折叠优化input_names=['input'], # 输入名称output_names=['output'], # 输出名称dynamic_axes={'input': {0: 'batch_size'}, # 动态批次大小'output': {0: 'batch_size'}})print(f"Model exported to {save_path}")# 使用示例
model = YourModel()
model.load_state_dict(torch.load('model.pth'))
export_to_onnx(model, (1, 3, 224, 224), 'model.onnx')
2.2 验证导出模型
导出后必须进行全面验证,包括结构检查和数值对比:
- 结构验证
import onnx
import onnxruntime
import numpy as npdef verify_onnx_structure(onnx_path):# 加载并检查模型结构onnx_model = onnx.load(onnx_path)onnx.checker.check_model(onnx_model)# 打印模型信息print("模型输入:")for input in onnx_model.graph.input:print(f"- {input.name}: {input.type.tensor_type.shape}")print("\n模型输出:")for output in onnx_model.graph.output:print(f"- {output.name}: {output.type.tensor_type.shape}")
- 数值精度对比
def compare_outputs(model, onnx_path, input_data):# PyTorch结果model.eval()with torch.no_grad():torch_output = model(torch.from_numpy(input_data))# ONNX结果ort_output = verify_onnx_model(onnx_path, input_data)# 比较差异diff = np.abs(torch_output.numpy() - ort_output).max()print(f"最大误差: {diff}")return diff < 1e-5
- 验证 ONNX 模型
import onnx
import onnxruntime
import numpy as npdef verify_onnx_model(onnx_path, input_data):# 加载ONNX模型onnx_model = onnx.load(onnx_path)onnx.checker.check_model(onnx_model)# 创建推理会话ort_session = onnxruntime.InferenceSession(onnx_path)# 准备输入数据ort_inputs = {ort_session.get_inputs()[0].name: input_data}# 运行推理ort_outputs = ort_session.run(None, ort_inputs)return ort_outputs[0]input_data = np.random.randn(1, 3, 224, 224).astype(np.float32)
output = verify_onnx_model('model.onnx', input_data)
2.3 ONNX模型优化
使用ONNX Runtime提供的优化工具进一步提升性能:
import onnxruntime as ort
from onnxruntime.transformers import optimizerdef optimize_onnx_model(onnx_path, optimized_path):# 创建优化器配置opt_options = optimizer.OptimizationConfig(optimization_level=99, # 最高优化级别enable_gelu_approximation=True,enable_layer_norm_optimization=True,enable_attention_fusion=True)# 优化模型optimized_model = optimizer.optimize_model(onnx_path, 'cpu', # 或 'gpu'opt_options)# 保存优化后的模型optimized_model.save_model_to_file(optimized_path)print(f"优化后的模型已保存至 {optimized_path}")
optimizer.optimize_model()
第二个参数是优化目标设备,支持 ‘cpu’ 或 ‘gpu’。- 优化目标设备:指定模型优化时的目标硬件平台。例如:
- ‘cpu’:针对 CPU 进行优化(如调整算子、量化参数等)。
- ‘gpu’:针对 GPU 进行优化(如使用 CUDA 内核、张量核心等)。
*运行时设备:优化后的模型可以在其他设备上运行,但性能可能受影响。例如: - 针对 CPU 优化的模型可以在 GPU 上运行,但可能无法充分利用 GPU 特性。
- 针对 GPU 优化的模型在 CPU 上运行可能会报错或性能下降。
建议保持优化目标与运行设备一致以获得最佳性能。
- 优化目标设备:指定模型优化时的目标硬件平台。例如:
3. TorchScript格式导出
3.1 trace导出
适用于前向计算图结构固定的模型。
import torchdef export_torchscript_trace(model, input_shape, save_path):model.eval()example_input = torch.randn(input_shape)# 使用跟踪法导出traced_model = torch.jit.trace(model, example_input)traced_model.save(save_path)print(f"Traced model exported to {save_path}")return traced_model
3.2 script导出
适用于包含条件分支、循环等动态结构的模型。
import torch
import torch.nn as nn@torch.jit.script
class ScriptableModel(nn.Module):def __init__(self):super().__init__()self.conv = nn.Conv2d(3, 64, 3)self.relu = nn.ReLU()def forward(self, x):x = self.conv(x)x = self.relu(x)return xdef export_torchscript_script(model, save_path):scripted_model = torch.jit.script(model)scripted_model.save(save_path)print(f"Scripted model exported to {save_path}")return scripted_model
3.3 TorchScript模型验证
验证TorchScript模型的正确性:
def verify_torchscript_model(original_model, ts_model_path, input_data):# 原始模型输出original_model.eval()with torch.no_grad():original_output = original_model(input_data)# 加载TorchScript模型ts_model = torch.jit.load(ts_model_path)ts_model.eval()# TorchScript模型输出with torch.no_grad():ts_output = ts_model(input_data)# 比较差异diff = torch.abs(original_output - ts_output).max().item()print(f"最大误差: {diff}")return diff < 1e-5
4. 自定义算子处理
4.1 ONNX自定义算子
如需导出自定义算子,可通过ONNX扩展机制实现。
from onnx import helperdef create_custom_op():# 定义自定义算子custom_op = helper.make_node('CustomOp', # 算子名称inputs=['input'], # 输入outputs=['output'], # 输出domain='custom.domain')return custom_opdef register_custom_op():# 注册自定义算子from onnxruntime.capi import _pybind_state as CC.register_custom_op('CustomOp', 'custom.domain')
4.2 TorchScript自定义算子
可通过C++扩展自定义TorchScript算子。
from torch.utils.cpp_extension import load# 编译自定义C++算子
custom_op = load(name="custom_op",sources=["custom_op.cpp"],verbose=True
)# 在模型中使用自定义算子
class ModelWithCustomOp(nn.Module):def forward(self, x):return custom_op.forward(x)
4.3 自定义算子示例
下面是一个完整的自定义算子实现示例:
// custom_op.cpp
#include <torch/extension.h>torch::Tensor custom_forward(torch::Tensor input) {return input.sigmoid().mul(2.0);
}PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) {m.def("forward", &custom_forward, "Custom forward function");
}
# 在Python中使用
import torch
from torch.utils.cpp_extension import load# 编译自定义算子
custom_op = load(name="custom_op",sources=["custom_op.cpp"],verbose=True
)# 测试自定义算子
input_tensor = torch.randn(2, 3)
output = custom_op.forward(input_tensor)
print(output)
5. 模型部署示例
5.1 ONNXRuntime部署
import onnxruntime as ort
import numpy as np
from PIL import Image
import torchvision.transforms as transformsdef preprocess_image(image_path, input_shape):# 图像预处理transform = transforms.Compose([transforms.Resize((input_shape[2], input_shape[3])),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])image = Image.open(image_path).convert('RGB')image_tensor = transform(image).unsqueeze(0).numpy()return image_tensordef onnx_inference(onnx_path, image_path, input_shape=(1, 3, 224, 224)):# 加载ONNX模型session = ort.InferenceSession(onnx_path)# 预处理图像input_data = preprocess_image(image_path, input_shape)# 获取输入输出名称input_name = session.get_inputs()[0].nameoutput_name = session.get_outputs()[0].name# 执行推理result = session.run([output_name], {input_name: input_data})return result[0]
5.2 TorchScript部署
import torch
from PIL import Image
import torchvision.transforms as transformsdef torchscript_inference(model_path, image_path):# 加载TorchScript模型model = torch.jit.load(model_path)model.eval()# 图像预处理transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])])# 加载并处理图像image = Image.open(image_path).convert('RGB')input_tensor = transform(image).unsqueeze(0)# 执行推理with torch.no_grad():output = model(input_tensor)return output
6. 常见问题与解决方案
6.1 ONNX导出失败
问题: 导出ONNX时出现算子不支持错误
解决方案:
# 尝试使用更高版本的opset
torch.onnx.export(model, dummy_input, "model.onnx", opset_version=13)# 或替换不支持的操作
class ModelWrapper(nn.Module):def __init__(self, model):super().__init__()self.model = modeldef forward(self, x):# 替换不支持的操作为等效操作return self.model(x)
6.2 TorchScript跟踪失败
问题: 动态控制流导致trace失败
解决方案:
# 使用script而非trace
scripted_model = torch.jit.script(model)# 或修改模型结构避免动态控制流
class TraceFriendlyModel(nn.Module):def __init__(self, original_model):super().__init__()self.model = original_modeldef forward(self, x):# 移除动态控制流return self.model.forward_fixed(x)
6.3 推理性能问题
问题: 导出模型推理速度慢
解决方案:
# 1. 使用量化
from torch.quantization import quantize_dynamic
quantized_model = quantize_dynamic(model, {nn.Linear, nn.Conv2d}, dtype=torch.qint8)# 2. 使用TensorRT优化ONNX
import tensorrt as trt
# TensorRT优化代码...# 3. 使用ONNX Runtime优化
import onnxruntime as ort
session = ort.InferenceSession("model.onnx", providers=['CUDAExecutionProvider'])
7. 最佳实践
-
选择合适的导出格式
- ONNX:适合跨平台、跨框架部署,兼容性强
- TorchScript:适合PyTorch生态内部署,支持灵活性高
- 根据目标平台和性能需求选择
-
优化导出模型
- 使用合适的opset版本(建议11及以上)
- 启用常量折叠等优化选项
- 导出后务必验证模型正确性
- 考虑使用量化和剪枝优化模型大小
-
处理动态输入
- 设置动态维度(如batch_size)
- 测试不同输入大小,确保模型鲁棒性
- 记录支持的输入范围和约束
-
文档和版本控制
- 记录导出配置和依赖版本
- 保存模型元数据(如输入输出规格)
- 对模型文件进行版本化管理
- 维护模型卡片(Model Card)记录关键信息
-
调试技巧
- 使用ONNX Graph Viewer等可视化工具分析模型结构
- 使用Netron查看计算图和参数分布
- 比较原始与导出模型输出,检查数值精度差异
- 遇到兼容性问题时查阅官方文档和社区经验
8. 参考资源
- ONNX官方文档
- PyTorch TorchScript教程
- ONNX Runtime文档
- TensorRT开发者指南
- Netron模型可视化工具
📌 感谢阅读!若文章对你有用,别吝啬互动~
👍 点个赞 | ⭐ 收藏备用 | 💬 留下你的想法 ,关注我,更多干货持续更新!
相关文章:
[模型部署] 1. 模型导出
👋 你好!这里有实用干货与深度分享✨✨ 若有帮助,欢迎: 👍 点赞 | ⭐ 收藏 | 💬 评论 | ➕ 关注 ,解锁更多精彩! 📁 收藏专栏即可第一时间获取最新推送🔔…...
Neo4j 图书馆借阅系统知识图谱设计
一、数据模型设计 节点类型 读者(Reader) 属性: reader_id, name, age, gender, phone, email, register_date 图书(Book) 属性: book_id, title, author, publisher, publish_date, isbn, price, category 图书副本(BookCopy) 属性: copy_id, status (在馆/借出/维修), loca…...
android 安装openwrt 安正步骤
安装 QEMU 模拟器 bash 复制 编辑 pkg install wget pkg install qemu-utils pkg install qemu-system-aarch64-headless 可选 x86 模拟支持: bash 复制 编辑 pkg install qemu-system-x86-64-headless ✅ 下载 OpenWRT 镜像(armvirt 64) bash 复制 编辑 mkdir -p ~/openwr…...
大规模CFD仿真计算中,SIMPLE或者PISO算法中加速压力场方程迭代求解
文章目录 在SIMSOL或PISO算法中加速压力场方程的迭代求解是提高CFD计算效率的关键。以下从算法优化、数值技巧和并行计算等方面总结加速策略:**1. 压力方程求解器的选择与优化****2. 算法层面的加速****3. 离散格式与网格优化****4. 并行计算与硬件加速****5. 代码级…...
【C#】 lock 关键字
在 C# 里,lock 关键字就是对 Monitor.Enter/Exit 的简写。它的作用是保证“同一时刻只有一个线程能进入被保护的代码块”,从而避免多个线程同时修改同一个共享状态导致竞态条件(race condition)。 一、结合Jog 的例子讲解 // Mot…...
前端脚手架开发指南:提高开发效率的核心操作
前端脚手架通过自动化的方式可以提高开发效率并减少重复工作,而最强大的脚手架并不是现成的那些工具而是属于你自己团队量身定制的脚手架!本篇文章将带你了解脚手架开发的基本技巧,帮助你掌握如何构建适合自己需求的工具,并带着你…...
职坐标AIoT技能培训课程实战解析
职坐标AIoT技能培训课程以人工智能与物联网技术深度融合为核心,构建了“理论实战行业应用”三位一体的教学体系。课程体系覆盖Python编程基础、传感器数据采集、边缘计算开发、云端服务部署及智能硬件开发全链路,通过分层递进的知识模块帮助学员建立系统…...
Yocto Project 快速构建
此文为机器辅助翻译,仅供个人学习使用,如有翻译不当之处欢迎指正 1 Yocto 项目快速构建 1.1 欢迎! 本简短文档将引导您完成使用 Yocto Project 进行典型镜像构建的流程,并介绍如何为特定硬件配置构建环境。您将使用 Yocto Proj…...
git相关配置
git相关配置 欢迎使用Markdown编辑器修改Git默认编辑器为vimgit配置默认用户名和密码: 欢迎使用Markdown编辑器 修改Git默认编辑器为vim #方法1:直接执行 git config --global core.editor vim#方法2:修改git的配置文件.git/config文件&am…...
ci/cd全流程实操
本次采用架构,gitlab + jenkins + 镜像仓库+ k8s 准备工作 一、gitlab部署 拉取镜像 部署环境: macbook m2中docker部署gitlab (m2平台架构问题,这里只能用yrzr/gitlab-ce-arm64v8 这个容器镜像) docker pull yrzr/gitlab-ce-arm64v8 在 Docker 里,–privileged=tr…...
Python中in和is关键字详解和使用
在 Python 中,in 和 is 是两个常用但含义不同的关键字,初学者很容易混淆它们的用法。下面是关于它们的详细解释、注意事项及常见示例。 一、关键字 in:成员运算符 1. 功能 用于判断某个元素是否存在于序列(如列表、元组、字符串…...
ACM模式用Scanner和System.out超时的解决方案和原理
Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 🌱🌱个人主页:奋斗的明志 🌱🌱所属专栏:笔试强训 📚本系列文章为个人学…...
微服务中服务降级和异常的区别
在Java中,服务降级和异常处理是两个相关但不同的概念。它们的主要区别如下: 1. 服务降级(Service Degradation): 定义:服务降级是指在系统中某个服务或功能出现问题时,通过采取某些策略来降低服务的质量或…...
MYSQL创建索引的原则
创建索引的原则包括: 表中的数据量超过10万以上时考虑创建索引。 选择查询频繁的字段作为索引,如查询条件、排序字段或分组字段。 尽量使用复合索引,覆盖SQL的返回值。 如果字段区分度不高,可以将其放在组合索引的后面。 对于…...
29、魔法微前端——React 19 模块化架构
一、时空结界分割术(模块化架构设计) 1. 次元切割协议 // 主应用入口const HogwartsMain () > {const [subApps] useState({potion: React.lazy(() > import(./PotionShop)),library: React.lazy(() > import(./LibraryApp)),quidditch: R…...
【PmHub后端篇】PmHub 中缓存与数据库一致性的实现方案及分析
在软件开发项目中,缓存的使用十分普遍。缓存作为一种存储机制,能够暂时保存数据,从而加速数据的读取和访问。然而,当数据同时存在于缓存和数据库中时,如何保证两者的数据一致性成为了一个关键问题。在 PmHub 项目中&am…...
Verilog HDL 语言整理
Verilog HDL 语言 Verilog HDL 简介 硬件描述语言Hardware Description Language是一种用形式化方法即文本形式 来描述和设计数字电路和数字系统的高级模块化语言 Verilog HDL(Hardware Description Language)是一种硬件描述语言,用于建模…...
[250516] OpenAI 升级 ChatGPT:GPT-4.1 及 Mini 版上线!
目录 ChatGPT 迎来重要更新:GPT-4.1 和 GPT-4.1 mini 正式上线用户如何访问新模型?技术亮点与用户体验优化 ChatGPT 迎来重要更新:GPT-4.1 和 GPT-4.1 mini 正式上线 OpenAI 宣布在 ChatGPT 平台正式推出其最新的 AI 模型 GPT-4.1 和 GPT-4.…...
R语言学习--Day03--数据清洗技巧
在一般情况下,我们都是在数据分析的需求前提下去选择使用R语言。而实际上,数据分析里,百分之八十的工作,都是在数据清洗。并不只是我们平时会提到的异常值处理或者是整合格式,更多会涉及到将各种各样的数据整合&#x…...
文件系统交互实现
关于之前的搭建看QT控件文件系统的实现-CSDN博客,接下来是对本程序的功能完善,我想着是这样设计的,打开一个目录以后,鼠标选中一个项可以是目录,也可以是文件,右键可以出现一个菜单选择操作,比如…...
SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。
/// <summary> /// SqlHelper 实现类,支持多数据库,提供异步操作、自动重试、事务、存储过程、分页、缓存等功能。 /// </summary> public class SqlHelper : IDbHelper {private readonly IDbConnectionFactory _connectionFactory;private…...
DevExpressWinForms-RichEditControl-基础应用
RichEditControl-基础应用 在企业级WinForms应用开发中,富文本编辑与文档处理是常见需求。DevExpress WinForms的RichEditControl作为一款功能强大的富文本编辑控件,提供了媲美Microsoft Word的文档处理能力,支持复杂格式编辑、打印导出、界…...
Elasticsearch 索引副本数
作者:来自 Elastic Kofi Bartlett 解释如何配置 number_of_replicas、它的影响以及最佳实践。 更多阅读:Elasticsearch 中的一些重要概念: cluster, node, index, document, shards 及 replica 想获得 Elastic 认证?查看下一期 Elasticsearc…...
RabbitMQ 扇形交换器工作原理详解
目录 一、扇形交换器简介二、扇形交换器工作原理2.1 消息广播机制2.2 路由键的忽略三、代码示例3.1 生产者代码3.2 消费者代码四、实际应用场景4.1 日志收集系统4.2 实时通知系统4.3 事件驱动架构五、总结在 RabbitMQ 的众多交换器类型中,扇形交换器(Fanout Exchange)是一种…...
IDEA中springboot项目中连接docker
具体内容如下: 1、在Linux中安装docker 使用安装命令: apt-get install docker.io 还有一个是更新软件并安装docker: sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io 运行docker systemctl start …...
arxiv等开源外文书数据的获取方式
一、一些基本说明 开放API接口文档:https://info.arxiv.org/help/api/user-manual.html#2-api-quickstart研究领域分类说明文档:https://arxiv.org/category_taxonomy 二、基于url接口方式检索并获取数据 本质是get方式,在url中传检索参数…...
ChatGPT再升级!
近日,OpenAI 正式发布 GPT-4.1 和轻量级版本 GPT-4.1mini,并已全面上线 ChatGPT 平台,迅速引发全球 AI 圈热议,标志着 ChatGPT 在智能化和效率上再登新高峰。 GPT-4.1 是为编程与任务处理优化的高性能模型。相较前作 GPT-4o&#…...
23、电网数据管理与智能分析 - 负载预测模拟 - /能源管理组件/grid-data-smart-analysis
76个工业组件库示例汇总 电网数据管理与智能分析组件 1. 组件概述 本组件旨在模拟一个城市配电网的运行状态,重点关注数据管理、可视化以及基于模拟数据的智能分析,特别是负载预测功能。用户可以通过界面交互式地探索电网拓扑、查看节点状态、控制时间…...
#跟着若城学鸿蒙# web篇-获取定位
前言 在业务中,某些网页上需要获取用户的地理位置,然后按照用户搜索的兴趣点与用户的距离远近进行排序,这就需要h5能够获取到用户的位置。 由于 web 组件基于Chromium M114 版本开发,前端就可以使用navigator.geolocation.getC…...
前端批量下载文件打包为zip
多文件需要一次性下载为zip文件 这是近期遇到的一个需求,本身是多文件上传的,下载时单个下载太慢又繁杂,用户希望能一次性批量下载,就选择了jszip import axios from "axios" import JSZip from "jszip" im…...
Vue百日学习计划Day9-15天详细计划-Gemini版
重要提示: 番茄时钟: 每个番茄钟为25分钟学习,之后休息5分钟。每完成4个番茄钟,进行一次15-30分钟的长休息。灵活性: JavaScript 的概念较多,尤其是 this、原型链、闭包和异步编程,可能需要更多…...
MySQL8.x新特性:与mysql5.x的版本区别
MySQL8.x新特性 1.与mysql5.x的区别:MySQL8.x新特性:与mysql5.x的版本区别-CSDN博客 2.窗口函数(Window Functions):MySQL8.x新特性:窗口函数(Window Functions)-CSDN博客 引言 …...
RabbitMQ 消息模式实战:从简单队列到复杂路由(三)
精准投递:路由模式 路由模式详解 路由模式是 RabbitMQ 中一种功能强大且灵活的消息传递模式,它在发布订阅模式的基础上,引入了路由键(Routing Key)的概念,实现了消息的精准路由和分发 。在路由模式中&…...
STM32 定时器主从模式配置解析
STM32 定时器主从模式配置解析 下面这两行代码是配置STM32定时器主从模式的关键设置 代码功能解析 TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2); // 选择从模式输出的触发源 TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); // 选择从模式1. TIM_SelectInputTrigger(T…...
Leetcode76覆盖最小子串
覆盖最小子串 代码来自b站左程云 class Solution {public String minWindow(String str, String tar) {char[] s str.toCharArray();char[] t tar.toCharArray();int[] cnt new int[256];for (char cha : t) { cnt[cha]--;}int len Integer.MAX_VALUE;int debt t.length…...
Perl语言深度考查:从文本处理到正则表达式的全面掌握
阅读原文 前言:为什么Perl依然值得学习? "这个脚本用Perl写只需要5分钟!"——在当今Python大行其道的时代,你依然能在不少企业的运维部门听到这样的对话。Perl作为一门有着30多年历史的语言,凭借其强大的文…...
idea中Lombok失效的解决方案
Lombok 是一个 Java 库,旨在通过注解简化 Java 代码的编写,减少样板代码,提高开发效率。它通过自动生成常见的代码(如 getter、setter、构造函数等)来减少开发者的手动编码工作。 一般Lombok失效有四步排查方案&#…...
【LeetCode 热题 100】动态规划 系列
📁 70. 爬楼梯 状态标识:爬到第i层楼梯时,有多少种方法。 状态转移方程:dp[i] dp[i-1] dp[i-2],表示从走一步和走两步的方式。 初始化:dp[1] 1 , dp[2] 2。 返回值:dp[n],即走到…...
刷leetcodehot100返航版--双指针5/16
for (int i 0, j 0; i < n; i ) { while (j < i && check(i, j)) j ; // 具体问题的逻辑 } 常见问题分类: (1) 对于一个序列,用两个指针维护一段区间 (2) 对于两个序列,维护某种次序,比如归并排序中…...
DAY24元组和OS模块
元组 元组的特点: 有序,可以重复,这一点和列表一样元组中的元素不能修改,这一点非常重要,深度学习场景中很多参数、形状定义好了确保后续不能被修改。 很多流行的 ML/DL 库(如 TensorFlow, PyTorch, Num…...
CSS:三大特性
文章目录 一、层叠性二、继承性三、优先级 一、层叠性 二、继承性 可以在MDN网站上查看属性是否可以被继承 例如color 三、优先级...
Cross-Site Scripting(XSS)
1. XSS介绍 跨站脚本攻击(Cross-Site Scripting)简称XSS,人们经常将跨站脚本攻击(Cross Site Scripting)缩写为CSS,但这会与层叠样式表(Cascading Style Sheets,CSS)的缩…...
掌握HTML文件上传:从基础到高级技巧
HTML中input标签的上传文件功能详解 一、基础概念 1. 文件上传的基本原理 在Web开发中,文件上传是指将本地计算机中的文件(如图片、文档、视频等)传输到服务器的过程。HTML中的<input type"file">标签是实现这一功能的基础…...
WebRTC中的几个Channel
一、我指的是谁? 以视频为例,常见的有:MediaChannel、VideoMediaChannel、WebRtcVideoChannel、BaseChannel、VideoChannel,那么,为什么要这么多Channel,只写一个叫做SuperChannel行不行(很多程…...
【设计模式】- 行为型模式1
模板方法模式 定义了一个操作中的算法骨架,将算法的一些步骤推迟到子类,使得子类可以不改变该算法结构的情况下重定义该算法的某些步骤 【主要角色】: 抽象类:给出一个算法的轮廓和骨架(包括一个模板方法 和 若干基…...
容器化-k8s-使用和部署
一、K8s 使用 1、基本概念 集群: 由 master 节点和多个 slaver 节点组成,是 K8s 的运行基础。节点: 可以是物理机或虚拟机,是 K8s 集群的工作单元,运行容器化应用。Pod: K8s 中最小的部署单元,一个 Pod 可以包含一个或多个紧密相关的容器,这些容器共享网络和存储资源。…...
黑马k8s(九)
1.Pod-生命周期概述 2.Pod生命周期-创建和终止 3.Pod生命周期-初始化容器...
Android trace中CPU的RenderThread与GPU
Android trace中CPU的RenderThread与GPU RenderThread是系统的GPU绘制线程,GPU渲染就是通常所谓的硬件加速,如果应用关闭硬件加速,就没有了RenderThread,只有UI Thread,即Android主线程。 Android GPU渲染SurfaceFlin…...
测试工程师如何学会Kubernetes(k8s)容器知识
Kubernetes(K8s)作为云原生时代的关键技术之一,对于运维工程师、开发工程师以及测试工程师来说,都是一门需要掌握的重要技术。作为一名软件测试工程师,学习Kubernetes是一个有助于提升自动化测试、容器化测试以及云原生应用测试能力的重要过程…...
接触感知 钳位电路分析
以下是NG板接触感知电路的原理图。两极分别为P3和P4S,电压值P4S < P3。 电路结构分两部分,第一部分对输入电压进行分压钳位。后级电路使用LM113比较器芯片进行电压比较,输出ST接触感知信号。 钳位电路输出特性分析 输出电压变化趋势&a…...