2023年10月

国内文章

.NET 8 RC 2 发布,将在11月14日发布正式版

https://www.cnblogs.com/shanyou/p/17756172.html

微软于2023年10月10日发布了.NET 8 RC 2,预计在下个月的Net Conf 2023期间正式发布.NET 8。.NET 8的所有主要新功能已经推出,开发团队将在接下来的一个月内主要专注于改进功能和修复错误。此外,Tiobe编程语言排行榜显示,C#的上升趋势明显,预计在大约两个月内将超过Java。.NET团队还在官方博客上发布了一系列文章,介绍.NET 8框架以及相关的ASP.NET Core、MAUI、EF Core、Visual Studio 2022 17.8的功能特性。

OpenTelemetry学习笔记-Trace

https://mp.weixin.qq.com/s/X-aiCMaVIzcz0lSM22jpfQ

文章是关于OpenTelemetry的学习笔记,主要介绍了以下内容:

  • OpenTelemetry是一个可观测性的框架和工具包,目的是创建和管理遥测数据,如traces、metrics和logs。
  • OpenTelemetry有两个重要的优势:你可以拥有自己生成的数据,而不是被专有数据格式或工具;你可以学习一组API和约定。
  • OpenTelemetry中trace表示一组有序的事件,描述了分布式系统中一个操作的生命周期。每个trace由一系列的span组成,每个span描述了一个子任务或步骤。
  • OpenTelemetry中resource描述了程序正在消费的物理和虚拟信息结构,包括一些基本信息和配置设置。
  • OpenTelemetry提供了一套通用的server attributes,用于描述服务端的属性。

.NET静态代码织入——肉夹馍(Rougamo)发布2.0

https://www.cnblogs.com/nigture/p/17753498.html

"肉夹馍"是一种实现AOP的组件,主要特点是在编译时完成AOP代码织入,减少应用启动的初始化时间,提高服务可用性,还能对静态方法进行AOP。2.0版本推出了新功能,包括部分织入,用户可以根据需要选择使用的功能,避免无形中增加目标程序集的大小,提高运行效率。例如,如果只想在方法执行成功或失败时执行日志操作,不需要重写参数、修改返回值或处理异常,可以通过重写Features属性来选择使用到的功能。

.NET高性能开发-位图索引(一)

https://www.cnblogs.com/InCerry/p/dotnet-bitmap-index-part-1.html

本文主要讨论了如何使用.NET构建内存位图索引优化搜索引擎计算速度。以机票搜索为例,由于航班数据量大且实时变动,传统数据库无法满足实时搜索需求。业界解决方案是将数据加载到内存进行计算,但如何在短时间内处理大量数据仍是挑战。文章提出了使用位图索引的方法,通过构建和使用位图索引,可以优化搜索引擎的计算速度。文章还将深入讨论位图索引的性能,如何通过SIMD加速位图索引的计算,以及构建高效的Bitmap内存索引库等问题。

WPF 笔迹算法 从点集转笔迹轮廓

https://www.cnblogs.com/lindexi/p/17758666.html

本文介绍了笔迹算法,这是一种基础数学算法,可以将用户输入的点集(如鼠标轨迹点或触摸轨迹点)转换为可在界面上绘制显示的笔迹画面。虽然本文以WPF的笔迹算法为例,但其基础数学计算理论上适用于任何支持几何绘制的UI框架。文章从简单到复杂描述了笔迹算法,包括最简单的笔迹轨迹算法,即通过创建一条几何图形(如折线)来构建笔迹轨迹。

【源码解读(一)】EFCORE源码解读之创建DBContext查询拦截

https://www.cnblogs.com/1996-Chinese-Chen/p/17761733.html

本文主要讲解了EFCore源码的一些关键部分。首先,文章解释了AddDbContext的作用,它是EFCore提供的几种扩展方法之一,用于设置DbContext和DBContextOption的生命周期。如果DBContext的生命周期是单例,Option的生命周期也应设置为单例。如果设置Option的委托不为空,那么DBContext的构造函数必须有一个参数。此外,文章还介绍了如何在EFCore的服务中获取Web注入的服务,拦截查询的方式,使用缓存查询方法提升性能,以及如何托管EFCORE的IOC容器等内容。

使用 OpenTelemetry 构建 .NET 应用可观测性(4):ASP.NET Core 应用中集成 OTel

https://www.cnblogs.com/eventhorizon/p/17760641.html

本文介绍了如何在ASP.NET Core应用中集成OTel SDK,并使用elastic构建可观测性平台展示OTel的数据。elastic提供了一套完整的可观测性平台,并支持OpenTelemetry protocol (OTLP)协议。elastic apm部署相对复杂,可以参考elastic的官方文档进行部署或直接购买elastic cloud。为了方便学习,作者提供了一个elastic的docker-compose文件,包含了elasticsearch、kibana、apm-server和fleet-server等组件。启动完成后,还需要一些配置才能启用apm-server。

4款.NET开源的Redis客户端驱动库

https://www.cnblogs.com/Can-daydayup/p/17760613.html

本文推荐了四款.NET开源免费的Redis客户端驱动库。Redis是一个开源的NoSQL数据库。NewLife.Redis是一个以高性能处理大数据实时计算为目标的Redis客户端组件,支持.NETCore/.NET4.0/.NET4.5。csredis是.NET Core或.NET Framework 4.0+的Redis客户端,支持同步和异步客户端。FreeRedis是基于.NET的Redis客户端,支持.NET Core 2.1+、.NET Framework 4.0+以及Xamarin。StackExchange.Redis是一个基于.NET的高性能Redis客户端,提供了完整的Redis数据库功能支持,并且具有多节点支持、异步编程模型、Redis集群支持等特性。此外,还介绍了DotNetGuide技术交流群,提供.NET开发者分享自己优质文章的群组和获取更多全面的C#/.NET/.NET Core学习资料、视频、文章、书籍,社区组织,工具和常见面试题资源。

.NET微服务系列之Saga分布式事务案例实践

https://www.cnblogs.com/linguicheng/p/17728458.html

本文主要分享了使用Wing进行Saga分布式事务的实践案例,以“跨行转账”为例。假设有“中国农业银行”和“中国工商银行”的账户,需要从农业银行转账1000元到工商银行。这个过程被分为两个事务单元处理:1. 当前账户扣减1000元,定义一个事务单元的数据传输模型和实现类。如果事务策略是“向前恢复”,则只需实现“Commit”方法,否则还需实现“Cancel”方法。

.NET 8 候选版本 2 (RC2) 现已可用

https://www.cnblogs.com/hejiale010426/p/17756402.html

".NET 8 候选版本 2 (RC2)已经发布,包含了许多ASP.NET Core的新改进。这是今年晚些时候发布的最终.NET 8版本之前的最后一个候选版本,大部分计划中的功能和更改都已包含在此版本中。新功能包括服务器和中间件的HTTP日志扩展性和更新到IdentityModel 7x,API创作中的表单文件支持,SignalR的Typescript客户端有状态重新连接支持,以及Blazor的多项改进。要开始使用.NET 8 RC2中的ASP.NET Core,需要安装.NET 8 SDK。如果在Windows上使用Visual Studio,建议安装最新的Visual Studio 2022预览版。如果使用的是Visual Studio Code,可以尝试新的C# Dev Kit。"

Util应用框架 7.x 来了

https://www.cnblogs.com/xiadao521/p/Util-7x.html

Util是一个.Net平台的应用框架,旨在提升中小团队的开发能力。最新版本7.x与.Net最新稳定版本同步更新,代码经过完全重写,提升了模块化程度,增加了对本地化、多租户等需求的支持。Util使用NgZorro作为UI基础组件库,封装了NgZorro绝大部分组件,并对常用功能进行扩展。新版本还集成和封装了Dapr微服务框架的几个常见构造块,并开发了基于Razor引擎的简易代码生成器。Util的所有项目发布时会在Github和Gitee进行同步更新。

Bridge 桥接模式简介与 C# 示例【结构型2】【设计模式来了_7】

https://www.cnblogs.com/hnzhengfy/p/SJMSLL_Bridge.html

本文介绍了桥接模式,这是一种结构型设计模式,通过将抽象与实现分离,实现松耦合。桥接模式可以使抽象和实现独立扩展,不会相互影响。例如,学生和餐品可以看作两个变化的类,老师就像桥接模式中的桥,学生想吃什么套餐,可以通过老师来对应到具体的套餐类别。桥接模式的优点包括分离抽象接口及其实现部分,提高系统的可扩展性,减少子类的个数。但使用桥接模式会增加系统的理解与设计难度,且使用范围具有一定的局限性。在游戏开发、网络编程、图形界面开发等场景中,桥接模式都有实际应用。

Semantic Kernel .NET SDK 的 v1.0.0 Beta1 发布

https://www.cnblogs.com/shanyou/p/17758153.html

Semantic Kernel(SK)是一个开源的SDK,将大型语言模型与流行的编程语言相结合,支持Java、Python和C#。它提供了添加内存和AI服务的连接器,支持来自不同提供商的插件,简化了AI服务的集成。SK的.NET SDK的v1.0.0 Beta1已发布,包括多项更改和改进,如将包和类从“技kill”重命名为“插件”,添加对多个AI模型的支持,重构规划器和内存配置等。如果需要从0.24版本升级到v1.0.0 Beta1,需要更新NuGet包和代码。此外,本文还介绍了如何简单地开始使用Semantic Kernel。

轻量通讯协议 --- MQTT

https://www.cnblogs.com/pandefu/p/17755762.html

本文介绍了MQTT(Message Queuing Telemetry Transport),这是一种轻量级的消息传输协议,常用于物联网和传感器网络中的通信。MQTT的特点包括轻量级、发布/订阅模型、可靠性、持久会话、QoS(Quality of Service)和适应性。MQTT还提供了QoS机制,以确保消息的可靠传递。此外,文章还介绍了MQTTnet,这是一个开源的、基于MQTT的通信的高性能.NET库。最后,文章介绍了Windows下的MQTT消息服务器的安装使用,包括Mosquitto和EMQX两种常见的MQTT服务器软件。

Skywalking APM监控系列(一丶.NET5.0+接入Skywalking监听)

https://www.cnblogs.com/GuZhenYin/p/17757705.html

本文主要介绍了Skywalking的使用和部署。Skywalking是一款分布式链路追踪组件,用于解决微服务架构中的问题,如服务故障定位、响应延迟原因分析、性能瓶颈定位等。Skywalking具有多种监控手段,支持多语言,轻量高效,模块化,并提供优秀的可视化解决方案。文章还详细介绍了如何通过Docker部署Skywalking和ES数据库。

C#学习笔记--复杂数据类型、函数和结构体

https://www.cnblogs.com/TonyCode/p/17757597.html

本文介绍了C#的复杂数据类型,包括枚举、数组和结构体。枚举是整型常量的集合,可以方便表示对象的各种状态,例如怪物的种类、玩家的动作状态等。数组是存储同一种特定变量类型的有序数据集合,可以是一维数组或多维数组。结构体是任意变量类型的数据组合成的数据块。这些复杂数据类型在编程中有广泛的应用,可以提高代码的可读性和可维护性。

Asp-Net-Core开发笔记:EFCore统一实体和属性命名风格

https://www.cnblogs.com/deali/p/17751279.html

本文介绍了如何在C#和数据库中实现命名风格的转换。在C#编码规范中,类和属性使用大写驼峰命名,而数据库通常使用小写蛇形命名。FreeSQL内置了命名风格转换功能,可以实现PascalCase到snake_case的转换。而EFCore没有这个功能,需要我们自行实现。我们可以使用正则表达式来实现这个功能,写一个扩展方法,该方法会在每个小写字母/数字与大写字母之间添加下划线,并把整个字符串转换为小写。然后,我们可以重写DbContext的OnModelCreating方法,对表名、列名、key、index的名称做转换。

使用Docker buildx 为 .NET 构建多平台镜像

https://www.cnblogs.com/shanyou/p/17765247.html

.NET团队的博客介绍了如何使用Docker的buildx工具在.NET 7以上的平台上构建多平台镜像。buildx是Docker的一个构建工具,可以快速、高效地构建Docker镜像,并支持多种平台的构建。用户可以在单个命令中构建多种架构的镜像,例如x86和ARM架构,而无需手动操作多个构建命令。buildx还支持Dockerfile的多阶段构建和缓存,这可以大大提高镜像构建的效率和速度。要使用buildx,需要Docker Engine版本号大于等于19.03。使用buildx构建跨平台镜像,需要先创建一个builder。然后,可以使用一条命令构建跨平台镜像。

Composite 组合模式简介与 C# 示例【结构型3】【设计模式来了_8】

https://www.cnblogs.com/hnzhengfy/p/SJMLLL_Composite.html

本文介绍了组合设计模式,这是一种针对树形结构的设计模式,所有节点实现同一接口,具有相同的操作,可以遍历全部节点。组合模式通过树形结构组合对象,表示部分和整体层次,属于结构型模式,多用于递归。优点包括高层模块调用简单,节点自由,简化了客户端代码。缺点包括叶子节点可能继承不需要的方法,组合类的引用开销可能大,需要运行时判断特殊组件。适用场景包括客户端可以忽略组合对象与单个对象的差异,以及对象层次具备整体和部分,呈树形结构。最后,文章提供了一个代码示例来解释这个概念。

OpenSSL 生成 RootCA (根证书)并自签署证书(支持 IP 地址)

https://www.cnblogs.com/aobaxu/p/17754721.html

本文介绍了如何在Ubuntu 22.04机器上生成HTTPS证书。首先,生成根CA的私钥和证书。然后,为特定IP(例如10.12.0.2)生成私钥和证书请求文件。接着,创建证书扩展文件以确保签名的证书能用作服务器身份验证。最后,使用根CA的证书为特定IP签名证书。此外,还介绍了如何在Ubuntu、CentOS和Windows上信任根CA的证书,以及如何在ASP.NET CORE应用中使用生成的证书。

为.NET打开新大门:OpenVINO.NET开源项目全新发布

https://www.cnblogs.com/sdflysha/p/20231015-sdcb-openvino-net.html

本文介绍了OpenVINO.NET开源项目的全新发布。OpenVINO是Intel开发的一款开源工具包,用于优化深度学习模型并进行推理部署,支持跨不同的Intel硬件平台。然而,对于.NET世界来说,OpenVINO的C API并没有一个合适且高质量的封装,因此作者开发了OpenVINO.NET项目。使用OpenVINO.NET的最简单方法是使用作者发布的NuGet包,包括Sdcb.OpenVINO和Sdcb.OpenVINO.runtime.win-x64等。作者还发布了一个基于Linux的镜像sdflysha/openvino-base,用于减轻部署压力。

详解.NET依赖注入中对象的创建与“销毁”

https://www.cnblogs.com/tenleft/p/17766501.html

本文主要介绍了DI容器如何创建和销毁对象。DI容器可以注册类型并创建其实例,如果类型实现了IAsyncDisposable或IDisposable接口,DI容器还会在适当的时候调用对象的DisposeAsync或Dispose方法。文章详细解释了DI容器中类的三种生命周期:Singleton(单例)、Scoped(局部单例)和Transient(每次都创建新对象)。在ASP.NET CORE中,每次请求会创建一个Scope,生命周期为Scoped的类在一次请求中只会创建一次。最后,文章深入探讨了ServiceProvider类在对象创建和销毁过程中的关键作用。

【分段传输】c#使用IAsyncEnumerable实现流式分段传输

https://www.cnblogs.com/1996-Chinese-Chen/p/17776939.html

本文主要讨论了使用C#的IAsyncEnumerable和ajax实现流式传输的方法。在使用SSE进行流式传输时,存在连接独占和数据格式固定的问题。而使用C#的IAsyncEnumerable可以解决这些问题,但返回的数据是在之前返回的基础上进行累加,需要自己处理。文章中提供了一个使用ajax实现的例子,通过监听请求的进度,可以获取到每一次写了哪些东西,从而实现流传输。同时,群友也提供了fetch的实现代码。

VS Code C# 开发工具包正式发布

https://www.cnblogs.com/Can-daydayup/p/17780747.html

微软正式发布了Visual Studio Code C#开发工具包,经过四个月的测试和调整,修复了350多个问题,并进行了300多项改进。C#开发工具包旨在提高在VS Code中使用C#的工作效率,它与C#扩展协同工作,打造了一个高性能、可扩展且灵活的工具环境。该工具包由一组VS Code扩展组成,提供丰富的C#编辑体验、AI驱动的开发、解决方案管理和集成测试。C#开发工具包的发布,提升了.NET的开发和工作效率。

Avalonia 实现视频聊天、远程桌面(源码,支持Windows、Linux、国产OS)

https://www.cnblogs.com/shawshank/p/17761146.html

本文介绍了基于.NET Core的跨平台UI框架Avalonia,它可以运行在任何支持.NET Core的平台上,包括Windows和Linux等。作者以一个视频聊天的Demo为例,展示了Avalonia的应用,该Demo支持视频聊天和远程桌面功能。用户可以向其他在线用户发送视频聊天或远程桌面请求,接受或拒绝其他用户的请求,开启视频聊天或远程桌面连接,也可以主动断开连接。该Demo的开发环境包括Visual Studio 2022,.NET Core 3.1和C#语言。

字符串 - 不可变性与驻留池

https://www.cnblogs.com/pandefu/p/17771369.html

本文主要讨论了字符串的性能优化,特别是StringBuilder和字符串驻留池的使用。StringBuilder由于其可变性,可以在原地修改字符串,避免了频繁的内存分配和回收,提高了性能。而字符串驻留池则是一种内存管理机制,它存储了字符串字面值的唯一实例,减少了内存使用并提高了性能。字符串的不可变性使得多个字符串字面值可以共享相同的内存实例,节省内存。此外,字符串驻留池的存在还带来了内存节省、性能提升、可靠性和代码简化等优点。

如何通过SK集成ChatGPT实现DotNet项目工程化?

https://www.cnblogs.com/hejiale010426/p/17771582.html

本文介绍了如何实现智能助手服务的天气插件。首先,我们需要了解SemanticKernel,它是一个SDK,将大型语言模型与传统编程语言集成在一起。然后,我们需要在项目中添加IKernel,OpenAIOptions.Model和OpenAIOptions.Key。在项目中,我们还有一个plugins文件夹,这是提供的插件目录。在BasePlugin目录下,有一个识别意图的插件。此外,config.json对应当前插件的一些参数配置,skprompt.txt则是当前插件使用的prompt。最后,我们需要注入IKernel。

[MAUI]深入了解.NET MAUI Blazor与Vue的混合开发

https://www.cnblogs.com/jevonsflash/p/17772897.html

本文介绍了如何在.NET MAUI中结合Vue进行混合开发,使得开发者可以使用熟悉的Vue语法,而无需重写现有项目。文章详细阐述了如何创建MAUI项目和Vue应用,并将Vue作为MAUI的一部分,使得在MAUI项目中可以直接使用Vue。同时,Vue的渐进性特性使得开发者可以根据需要逐步使用其框架特性。此外,文章还介绍了如何使用element-ui组件库,以及JavaScript和原生代码的交互方式。

记一次 .NET某新能源检测系统 崩溃分析

https://www.cnblogs.com/huangxincheng/p/17767410.html

本文描述了一位朋友的程序偶尔会崩溃,作者使用WinDbg工具进行分析。通过命令
!analyze -v
,作者发现崩溃点异常,且异常状态
80000004
在微软官方文档中显示为单步跟踪造成,这是作者首次遇到的情况。尽管自动化分析的信息不尽人意,但作者根据经验,查看了异常前的状态,寻找新的线索。

通过 Radius 实现Dapr 云原生应用程序开发协作

https://www.cnblogs.com/shanyou/p/17775795.html

微软Azure孵化团队推出了名为Radius的新开放应用程序平台,这是一个开源项目,支持在私有云、Microsoft Azure和Amazon Web Services上部署应用程序。该团队还推出了多个流行的开源项目,如Dapr、KEDA和Copacetic,这些都是云原生计算基金会(CNCF)项目。Dapr是一个分布式应用程序运行时,为开发现代应用程序提供了新方法,可以安装在任何可以运行Docker的计算机上。然而,基于Dapr开发的应用程序的构建、管理和运营存在挑战。为此,微软Azure孵化团队发布了Radius,该平台将应用程序置于每个开发阶段的中心,重新定义应用程序的构建、管理与理解方式。

探究 - C# .NET 代码混淆/加壳

https://www.cnblogs.com/magicMaQaQ/p/17702951.html

本文介绍了如何使用Obfuscar工具进行.NET代码混淆。首先,通过NuGet在项目中安装Obfuscar。然后,找到Obfuscar.Console.exe并将其复制到需要加密的文件夹中。最后,创建一个名为Obfuscar.xml的文件,设置相关参数,如输入路径、输出路径和是否保留公共API等。通过这种方式,可以有效地保护.NET代码,防止被轻易阅读和修改。

IL编织器 - Fody

https://www.cnblogs.com/pandefu/p/17775991.html

"Fody"是一个用于.NET程序集的可扩展工具,它可以在构建过程中操纵程序集的中间语言(IL)。Fody通过可扩展的插件模型消除了大量需要了解MSBuild和Visual Studio的API的底层代码。Fody使用Mono.Cecil和基于插件的方法在编译时修改.NET程序集的IL,不需要额外的安装步骤来构建,不需要部署运行时依赖项。此外,基于Fody库,诞生了许多插件库,如AutoProperties.Fody,PropertyChanged.Fody,InlineIL.Fody等,为用户提供了更多的功能和便利。

.NET开源简单易用、内置集成化的控制台、支持持久性存储的任务调度框架 - Hangfire

https://www.cnblogs.com/Can-daydayup/p/17766499.html

本文介绍了.NET开源任务调度框架Hangfire。Hangfire是一个简单易用的库,可以在.NET应用程序中执行后台的、延迟的和定期的任务,无需使用Windows服务或任务计划程序。它具有简单易用、可靠性强、高性能、扩展性好、持久化存储、任务监控和多种任务类型支持等特点。Hangfire可以与Redis、SQL Server、SQL Azure和MSMQ集成,提供了多种持久化存储方案。此外,Hangfire还提供了多种监控工具,可以实时查看任务的执行情况、错误信息、性能指标等。

Util应用框架Web Api开发环境搭建

https://www.cnblogs.com/xiadao521/p/17769405.html

本文主要介绍了如何使用Util应用框架开发项目,包括搭建开发环境和安装Visual Studio企业版。首先,需要安装Windows 10或以上版本的操作系统,然后下载并安装Visual Studio企业版,过程中需要联网。安装完成后,需要重启电脑。然后,打开Visual Studio,创建一个Web Api项目,以验证Visual Studio是否安装成功。在创建项目时,选择ASP.NET Core Web API项目类型,框架选择.Net 7.0。

C# 实现MD5加密

https://www.cnblogs.com/yangyongdashen-S/p/YiRenXiAn_CSharp_MD5.html

本文介绍了在C#中使用MD5进行数据加密的方法。MD5是一种hash算法,可以对任意长度的数据进行加密,生成固定长度的消息摘要,且加密结果不可逆。在C#中,可以使用MD5CryptoServiceProvider和MD5两种类型进行MD5加密,但在.NET6及以上版本中,MD5CryptoServiceProvider已过时,建议使用MD5。加密后的数据可以通过BitConverter方法或循环字节数组转成字符串的方式转换为32位数字和字母组成的字符串。此外,文件、图片等其他数据也可以转换成字节数组进行加密。完整的帮助类已上传至Gitee,可供下载使用。

再学Blazor - 扩展方法

https://www.cnblogs.com/known/p/17766595.html

本文主要介绍了Blazor组件的扩展方法实现思路。扩展方法是C#类型添加新方法的一种方式,可以对任何类型进行扩展,只需新建一个扩展类型。扩展方法需要添加扩展类和方法,都必须声明static修饰符,方法的第一个参数必须是扩展类型,并有this关键字。文章还介绍了如何扩展HTML元素和自定义组件,以及如何使用RenderTreeBuilder的原生方法。最后,文章提供了一个HTML元素扩展类的代码示例,用于扩展HTML元素。

一款简单漂亮的WPF UI - AduSkin

https://www.cnblogs.com/Can-daydayup/p/17778563.html

本文推荐了一款简单漂亮的WPF UI库——AduSkin。WPF是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的Windows应用。AduSkin是一款融合多个开源框架组件的WPF UI,为个人定制的UI,可供学者参考和使用。在Nuget搜索"AduSkin"即可直接导包使用。更多项目实用功能和特性,可以前往项目开源地址查看。此外,该项目已被收录到C#/.NET/.NET Core优秀项目和框架精选中。

主题

.NET 2023 年 10 月更新 – .NET 7.0.12、.NET 6.0.23 - .NET 博客

https://devblogs.microsoft.com/dotnet/october-2023-updates/

.NET 7 和 6 的 2023 年 10 月更新已发布。

此版本包括多个错误修复和改进以及三个安全修复。

宣布 .NET 8 候选版本 2 - .NET 博客

https://devblogs.microsoft.com/dotnet/announcing-dotnet-8-rc2/

.NET 8 候选版本 2 已发布。

  • .NET 库包自述文件
  • MSBuild+ 基于 CLI 的简单项目评估
  • SDK容器发布:发布到tar.gz存档
  • .NET 的张量基元简介

.NET 8 候选版本 2 中的 ASP.NET Core 更新 - .NET 博客

https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-8-rc-2/

关于使用 .NET 8 候选版本 2 更新 ASP.NET Core。

  • 服务器和中间件
    • HTTP 日志记录可扩展性
    • 更新到 IdentityModel 7x
  • API 编写
    • 支持具有新表单绑定的表单文件
    • SignalR
    • 对 TypeScript 客户端的状态重新连接支持
  • Blazor
    • 与 Blazor Web Apps 的全球交互
    • Blazor WebAssembly 模板更新
    • 文件范围@rendermode Razor指令
    • 增强的导航和表单处理改进
    • 当交互式服务器组件消失时连接断开
    • 改进的表单模型绑定
    • 将 HttpContext 作为级联参数访问
    • Blazor Web 应用程序中的持久组件
    • 将密钥服务注入组件
    • 支持对话框取消和关闭事件
    • 错误页面支持
    • 身份
    • Blazor 身份用户界面
    • 单页应用程序(SPA)
    • 从命令行运行新的 SPA 模板

EF Core 8 候选版本 2:EF8 中的较小功能 - .NET 博客

https://devblogs.microsoft.com/dotnet/announcing-ef8-rc2/

介绍 Entity Framework Core 8 候选版 2 的发布以及 EF Core 8 中的新功能。

  • 哨兵值和数据库默认值
  • 更好的执行更新和执行删除
  • 更好地使用“IN”查询
  • SQL Azure/SQL Server 中的数字行版本
  • 消除括号

在 .NET 8 候选版本 2 中宣布 .NET MAUI:更高质量 - .NET 博客

https://devblogs.microsoft.com/dotnet/announcing-dotnet-maui-in-dotnet-8-rc-2/

关于 .NET 8 候选版本 2 中的 .NET MAUI 更新。

除了介绍此版本中的质量改进之外,文章还提到了针对 .NET 7 的 .NET MAUI 服务版本 8 的发布以及与 Xcode 15 和 Android 14 的兼容性。

.NET Framework 2023 年 10 月安全和质量汇总更新 - .NET 博客

https://devblogs.microsoft.com/dotnet/dotnet-framework-october-2023-security-and-quality-rollup-updates/

.NET Framework 的 2023 年 10 月安全修复程序和累积更新已发布。

此版本不包含任何新的安全修复,但包含一些错误修复。

VMMap v3.4 - Microsoft 社区中心

https://techcommunity.microsoft.com/t5/sysinternals-blog/vmmap-v3-4/ba-p/3958601VMMap
v3.4 已发布。

VMMap是Windows上的内存分析工具。此版本还支持 .NET 6 到 8。

https://x.com/sysinternals/status/1714731087119675416?s=12

ASP.NET Core 8 中的性能改进 - .NET 博客

https://devblogs.microsoft.com/dotnet/performance-improvements-in-aspnet-core-8/

关于 .NET 8 候选发布版 2 中的 ASP.NET Core 性能改进。

  • 服务器
    • Kestrel
    • HTTP.sys
  • 原生AOT
  • 请求委托生成器
  • 运行时 API
    • SearchValues
    • Span
    • FrozenDictionary
  • 其他
    • 正则表达式
    • 分析仪
    • 字符串生成器

Visual Studio 2022 17.8 预览版 3 现已推出!- Visual Studio 博客

https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-8-preview-3-is-here/

Visual Studio 2022 17.8 预览版 3 已发布。

  • 生产力
    • Visual Studio更新通知
  • C++ 游戏开发
    • 虚幻引擎宏说明符建议
    • 结构化诊断
  • 将 SQL Server Data Tools 从 MDS 3.0 升级到 MDS 5.0

Visual Studio 中的 F# 代码修复大修 - .NET 博客

https://devblogs.microsoft.com/dotnet/overhauled-fsharp-code-fixes-in-visual-studio/

在 Visual Studio 中修复 F# 代码的改进。

.NET Conf 2023 议程

https://www.dotnetconf.net/agenda

.NET Conf 2023 的时间表/会议列表已发布。

https://x.com/dave_dotnet/status/1711432833594532083?s=12

发布版本 v2.58.0 · grpc/grpc-dotnet

https://github.com/grpc/grpc-dotnet/releases/tag/v2.58.0

gRPC (grpc-dotnet) v2.58.0 已发布。

此版本包括多个错误修复、调试改进以及从某些项目中删除 .NET Standard 1.5。

文章、幻灯片等

使用 .NET MAUI 和 Evergine 构建 3D 应用程序和内容 - .NET 博客

https://devblogs.microsoft.com/dotnet/dotnet-maui-3d-app-with-evergine/

介绍如何组合 .NET MAUI 和 Evergine 以在 .NET MAUI 应用程序之上托管 3D。

在 .NET 项目中使用 Stryker 进行突变测试

https://medium.com/@hamed.shirbandi/mutation-testing-with-stryker-in-net-projects-ff1f05ddce8f

了解如何使用 Stryker 在 .NET 项目中执行突变测试。

使用 Husky.NET 进行预提交挂钩 - 在 Git 提交之前构建、格式化和测试您的 .NET 应用程序

https://www.code4it.dev/blog/husky-dotnet-precommit-hooks/

介绍如何使用 Git 提交挂钩通过 Husky.NET 进行构建、测试、格式化等。

混合 C# 和 Rust - 互操作

https://fractalfir.github.io/generated_html/rustc_codegen_clr_v0_0_3_2.html

有关为 Rust 开发针对 .NET 的后端的系列。本文涉及实现和考虑如何从 Rust 调用 .NET。

C# 中双精度数的内存对齐

https://minidump.net/memory-alignment-of-doubles-in-c-1d13e3ce741

深入研究 .NET 中的双精度(64 位浮点)数组内存对齐。

如何在 EF Core 中将 UTC 保存的日期和时间转换并显示为 JST

https://zenn.dev/hat_kotap/articles/785960b233e5f0

如何使用 Entity Framework Core 和 PostgreSQL 在数据库中存储 UTC 日期和时间,并在显示时将其显示为 JST。

Rider 2023.3 EAP 3:全局使用支持的改进等等。| .NET 工具博客

https://blog.jetbrains.com/dotnet/2023/10/17/rider-2023-3-eap-3/

Rider 2023.3 EAP 3 已发布。

此版本包括改进的对全局使用的支持、对无根容器的支持、改进的 HTTP 客户端中的 JSON 请求正文完成、URL 路径引用的自动代码完成、AI 助手插件的更新等等。

.NET 8 中 Docker 映像的更新:探索 .NET 8 预览版 - 第 10 部分

https://andrewlock.net/exploring-the-dotnet-8-preview-updates-to-docker-images-in-dotnet-8/

使用 .NET 8 更新的 Docker 映像的详细说明。

RazorSlices - 使用 ASP.NET Core 最小 API 的 Razor 视图

https://khalidabuhakmeh.com/razorslices-razor-views-with-aspnet-core-minimal-apis

引入 RazorSlices,它允许您通过最少的 API 使用 Razor,而无需依赖 ASP.NET Core MVC 或 Razor Pages。

更好地查看 Visual Studio 活动日志

https://dev.to/karenpayneoregon/view-visual-studio-activity-logs-better-2id8

如何检索和查看 Visual Studio 本身的活动日志。

使用 Scrutor 改进 ASP.NET Core 依赖注入

https://dev.to/milanjovanovictech/improving-aspnet-core-dependency-injection-with-scrutor-48e3

如何使用 Scrutor 来处理 ASP.NET Core 的依赖注入,它扩展了 Microsoft.Extensions.DependencyInjection。

.NET Conf 2023 上的 Visual Studio 创新:节省时间 - Visual Studio 博客

https://devblogs.microsoft.com/visualstudio/visual-studio-innovations-at-net-conf-2023-save-the-date/

请注意,.NET Conf 2023 上将介绍 Visual Studio。

C# 13 的计划

https://ufcpp.net/blog/2023/10/triage2023/

关于 C# 13 的最近分类。

将 Blazor 组件渲染为字符串:探索 .NET 8 预览 - 第 9 部分

https://andrewlock.net/exploring-the-dotnet-8-preview-rendering-blazor-components-to-a-string/

了解如何使用 .NET 8 中添加的 HtmlRenderer 将 Blazor 组件呈现为字符串。

更新到预览版 3 (VS 2022 17.8) 后,MSFT_VSInstance 类从 WMI 目录中删除

https://developercommunity.visualstudio.com/t/MSFT_VSInstance-class-removed-from-WMI-c/10489629#T-N10491300

关于从 Visual Studio 2022 17.8 Preview 3 中的 WMI 目录中删除 MSFT_VSInstance。要继续使用它,您需要指定一个命名空间。

https://x.com/skitoy4321/status/1714857655154651192?s=12

Wrathmark:有趣的计算工作负载(第 1 部分)

https://ricomariani.medium.com/wrathmark-an-interesting-compute-workload-part-1-47d61e0bea43

按版本比较本机和 .NET JIT 性能。

库、存储库、工具等。

microsoft/vs-dapr:在 Visual Studio 中查看、管理和诊断 Dapr 服务。

https://github.com/microsoft/vs-dapr

在 Visual Studio 中支持(查看、管理和诊断)Dapr 的扩展。

由于它正在开发中,目前尚未从 Visual Studio Marketplace 分发。

Cysharp/Utf8StringInterpolation:ZString 的后继者;基于 UTF8 的零分配高性能字符串插值和 StringBuilder。

https://github.com/Cysharp/Utf8StringInterpolation

一个用于高效生成 UTF-8 字符串的库,主要使用字符串完成表达式。

https://x.com/neuuecc/status/1711911200274153689?s=12

网站、文档等

推文

https://x.com/chnasarre/status/1710940207950733496?s=12

image-20231024203434289

版权声明

由于笔者没有那么多时间对国内的一些文章进行整理,欢迎大家为《.NET周刊-国内文章》板块进行贡献,需要推广自己的文章或者框架、开源项目可以下方的项目地址提交Issue或者在我的微信公众号私信。

格式如下:

  • 10~50字左右的标题
  • 对应文章或项目网址访问链接
  • 200字以内的简介,如果太长会影响阅读体验

https://github.com/InCerryGit/.NET-Weekly

.NET性能优化交流群

相信大家在开发中经常会遇到一些性能问题,苦于没有有效的工具去发现性能瓶颈,或者是发现瓶颈以后不知道该如何优化。之前一直有读者朋友询问有没有技术交流群,但是由于各种原因一直都没创建,现在很高兴的在这里宣布,我创建了一个专门交流.NET性能优化经验的群组,主题包括但不限于:

  • 如何找到.NET性能瓶颈,如使用APM、dotnet tools等工具
  • .NET框架底层原理的实现,如垃圾回收器、JIT等等
  • 如何编写高性能的.NET代码,哪些地方存在性能陷阱

希望能有更多志同道合朋友加入,分享一些工作中遇到的.NET性能问题和宝贵的性能分析优化经验。
目前一群已满,现在开放二群。

如果提示已经达到200人,可以加我微信,我拉你进群:
ls1075

另外也创建了
QQ群
,群号: 687779078,欢迎大家加入。

抽奖送书活动预热!!!

感谢大家对我公众号的支持与陪伴!为庆祝公众号一周年,抽奖送出一些书籍,请大家关注公众号后续推文!

image-20230703203249615

本文深入探讨了长短时记忆网络(LSTM)的核心概念、结构与数学原理,对LSTM与GRU的差异进行了对比,并通过逻辑分析阐述了LSTM的工作原理。文章还详细演示了如何使用PyTorch构建和训练LSTM模型,并突出了LSTM在实际应用中的优势。

关注TechLead,分享AI与云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。

file

1. LSTM的背景

人工神经网络的进化

人工神经网络(ANN)的设计灵感来源于人类大脑中神经元的工作方式。自从第一个感知器模型(Perceptron)被提出以来,人工神经网络已经经历了多次的演变和优化。

  • 前馈神经网络(Feedforward Neural Networks)
    : 这是一种基本的神经网络,信息只在一个方向上流动,没有反馈或循环。
  • 卷积神经网络(Convolutional Neural Networks, CNN)
    : 专为处理具有类似网格结构的数据(如图像)而设计。
  • 循环神经网络(Recurrent Neural Networks, RNN)
    : 为了处理序列数据(如时间序列或自然语言)而引入,但在处理长序列时存在一些问题。

循环神经网络(RNN)的局限性

循环神经网络(RNN)是一种能够捕捉序列数据中时间依赖性的网络结构。但是,传统的RNN存在一些严重的问题:

  • 梯度消失问题(Vanishing Gradient Problem)
    : 当处理长序列时,RNN在反向传播时梯度可能会接近零,导致训练缓慢甚至无法学习。
  • 梯度爆炸问题(Exploding Gradient Problem)
    : 与梯度消失问题相反,梯度可能会变得非常大,导致训练不稳定。
  • 长依赖性问题
    : RNN难以捕捉序列中相隔较远的依赖关系。

由于这些问题,传统的RNN在许多应用中表现不佳,尤其是在处理长序列数据时。

LSTM的提出背景

长短时记忆网络(LSTM)是一种特殊类型的RNN,由Hochreiter和Schmidhuber于1997年提出,目的是解决传统RNN的问题。

  • 解决梯度消失问题
    : 通过引入“记忆单元”,LSTM能够在长序列中保持信息的流动。
  • 捕捉长依赖性
    : LSTM结构允许网络捕捉和理解长序列中的复杂依赖关系。
  • 广泛应用
    : 由于其强大的性能和灵活性,LSTM已经被广泛应用于许多序列学习任务,如语音识别、机器翻译和时间序列分析等。

LSTM的提出不仅解决了RNN的核心问题,还开启了许多先前无法解决的复杂序列学习任务的新篇章。

2. LSTM的基础理论

2.1 LSTM的数学原理

file

长短时记忆网络(LSTM)是一种特殊的循环神经网络,它通过引入一种称为“记忆单元”的结构来克服传统RNN的缺点。下面是LSTM的主要组件和它们的功能描述。

file

遗忘门(Forget Gate)

遗忘门的作用是决定哪些信息从记忆单元中遗忘。它使用sigmoid激活函数,可以输出在0到1之间的值,表示保留信息的比例。

[
f_t = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f)
]

其中,(f_t)是遗忘门的输出,(\sigma)是sigmoid激活函数,(W_f)和(b_f)是权重和偏置,(h_{t-1})是上一个时间步的隐藏状态,(x_t)是当前输入。

输入门(Input Gate)

输入门决定了哪些新信息将被存储在记忆单元中。它包括两部分:sigmoid激活函数用来决定更新的部分,和tanh激活函数来生成候选值。

[
i_t = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i)
]
[
\tilde{C}
t = \tanh(W_C \cdot [h
, x_t] + b_C)
]

记忆单元(Cell State)

记忆单元是LSTM的核心,它能够在时间序列中长时间保留信息。通过遗忘门和输入门的相互作用,记忆单元能够学习如何选择性地记住或忘记信息。

[
C_t = f_t \cdot C_{t-1} + i_t \cdot \tilde{C}_t
]

输出门(Output Gate)

输出门决定了下一个隐藏状态(也即下一个时间步的输出)。首先,输出门使用sigmoid激活函数来决定记忆单元的哪些部分将输出,然后这个值与记忆单元的tanh激活的值相乘得到最终输出。

[
o_t = \sigma(W_o \cdot [h_{t-1}, x_t] + b_o)
]
[
h_t = o_t \cdot \tanh(C_t)
]

LSTM通过这些精心设计的门和记忆单元实现了对信息的精确控制,使其能够捕捉序列中的复杂依赖关系和长期依赖,从而大大超越了传统RNN的性能。

2.2 LSTM的结构逻辑

长短时记忆网络(LSTM)是一种特殊的循环神经网络(RNN),专门设计用于解决长期依赖问题。这些网络在时间序列数据上的性能优越,让我们深入了解其逻辑结构和运作方式。

遗忘门:决定丢弃的信息

遗忘门决定了哪些信息从单元状态中丢弃。它考虑了当前输入和前一隐藏状态,并通过sigmoid函数输出0到1之间的值。

输入门:选择性更新记忆单元

输入门决定了哪些新信息将存储在单元状态中。它由两部分组成:

  • 选择性更新
    :使用sigmoid函数确定要更新的部分。
  • 候选层
    :使用tanh函数产生新的候选值,可能添加到状态中。

更新单元状态

通过结合遗忘门的输出和输入门的输出,可以计算新的单元状态。旧状态的某些部分会被遗忘,新的候选值会被添加。

输出门:决定输出的隐藏状态

输出门决定了从单元状态中读取多少信息来输出。这个输出将用于下一个时间步的LSTM单元,并可以用于网络的预测。

门的相互作用

  • 遗忘门
    : 负责控制哪些信息从单元状态中遗忘。
  • 输入门
    : 确定哪些新信息被存储。
  • 输出门
    : 控制从单元状态到隐藏状态的哪些信息流动。

这些门的交互允许LSTM以选择性的方式在不同时间步长的间隔中保持或丢弃信息。

逻辑结构的实际应用

LSTM的逻辑结构使其在许多实际应用中非常有用,尤其是在需要捕捉时间序列中长期依赖关系的任务中。例如,在自然语言处理、语音识别和时间序列预测等领域,LSTM已经被证明是一种强大的模型。

总结

LSTM的逻辑结构通过其独特的门控机制为处理具有复杂依赖关系的序列数据提供了强大的手段。其对信息流的精细控制和长期记忆的能力使其成为许多序列建模任务的理想选择。了解LSTM的这些逻辑概念有助于更好地理解其工作原理,并有效地将其应用于实际问题。

2.3 LSTM与GRU的对比

file
长短时记忆网络(LSTM)和门控循环单元(GRU)都是循环神经网络(RNN)的变体,被广泛用于序列建模任务。虽然它们有许多相似之处,但也有一些关键差异。

1. 结构

LSTM

LSTM包括三个门:输入门、遗忘门和输出门,以及一个记忆单元。这些组件共同控制信息在时间序列中的流动。

GRU

file
GRU有两个门:更新门和重置门。它合并了LSTM的记忆单元和隐藏状态,并简化了结构。

2. 数学表达

LSTM

LSTM的数学表达包括以下方程:

[
\begin{align
}
f_t & = \sigma(W_f \cdot [h_{t-1}, x_t] + b_f) \
i_t & = \sigma(W_i \cdot [h_{t-1}, x_t] + b_i) \
\tilde{C} t & = \tanh(W_C \cdot [h , x_t] + b_C) \
C_t & = f_t \cdot C_{t-1} + i_t \cdot \tilde{C} t \
o_t & = \sigma(W_o \cdot [h
, x_t] + b_o) \
h_t & = o_t \cdot \tanh(C_t)
\end{align

}
]

GRU

GRU的数学表达如下:

[
\begin{align
}
z_t & = \sigma(W_z \cdot [h_{t-1}, x_t] + b_z) \
r_t & = \sigma(W_r \cdot [h_{t-1}, x_t] + b_r) \
n_t & = \tanh(W_n \cdot [r_t \cdot h_{t-1}, x_t] + b_n) \
h_t & = (1 - z_t) \cdot n_t + z_t \cdot h_{t-1}
\end{align

}
]

3. 性能和应用

  • 复杂性
    : LSTM具有更复杂的结构和更多的参数,因此通常需要更多的计算资源。GRU则更简单和高效。
  • 记忆能力
    : LSTM的额外“记忆单元”可以提供更精细的信息控制,可能更适合处理更复杂的序列依赖性。
  • 训练速度和效果
    : 由于GRU的结构较简单,它可能在某些任务上训练得更快。但LSTM可能在具有复杂长期依赖的任务上表现更好。

小结

LSTM和GRU虽然都是有效的序列模型,但它们在结构、复杂性和应用性能方面有所不同。选择哪一个通常取决于具体任务和数据。LSTM提供了更精细的控制,而GRU可能更高效和快速。实际应用中可能需要针对具体问题进行实验以确定最佳选择。

3. LSTM在实际应用中的优势

file
长短时记忆网络(LSTM)是循环神经网络(RNN)的一种扩展,特别适用于序列建模和时间序列分析。LSTM的设计独具匠心,提供了一系列的优势来解决实际问题。

处理长期依赖问题

LSTM的关键优势之一是能够捕捉输入数据中的长期依赖关系。这使其在理解和建模具有复杂时间动态的问题上具有强大的能力。

遗忘门机制

通过遗忘门机制,LSTM能够学习丢弃与当前任务无关的信息,这对于分离重要特征和减少噪音干扰非常有用。

梯度消失问题的缓解

传统的RNN易受梯度消失问题的影响,LSTM通过引入门机制和细胞状态来缓解这个问题。这提高了网络的训练稳定性和效率。

广泛的应用领域

LSTM已被成功应用于许多不同的任务和领域,包括:

  • 自然语言处理
    : 如机器翻译,情感分析等。
  • 语音识别
    : 用于理解和转录人类语音。
  • 股票市场预测
    : 通过捕捉市场的时间趋势来预测股票价格。
  • 医疗诊断
    : 分析患者的历史医疗记录来进行早期预警和诊断。

灵活的架构选项

LSTM可以与其他深度学习组件(如卷积神经网络或注意力机制)相结合,以创建复杂且强大的模型。

成熟的开源实现

现有许多深度学习框架,如TensorFlow和PyTorch,都提供了LSTM的高质量实现,这为研究人员和工程师提供了方便。

小结

LSTM网络在许多方面表现出色,特别是在处理具有复杂依赖关系的序列数据方面。其能够捕捉长期依赖,缓解梯度消失问题,和广泛的应用潜力使其成为许多实际问题的理想解决方案。随着深度学习技术的不断进步,LSTM可能会继续在新的应用场景和挑战中展示其强大的实用价值。

4. LSTM的实战演示

4.1 使用PyTorch构建LSTM模型

file
LSTM在PyTorch中的实现相对直观和简单。下面,我们将演示如何使用PyTorch构建一个LSTM模型,以便于对时间序列数据进行预测。

定义LSTM模型

我们首先定义一个LSTM类,该类使用PyTorch的
nn.Module
作为基类。

import torch.nn as nn

class LSTMModel(nn.Module):
    def __init__(self, input_size, hidden_size, num_layers, output_size):
        super(LSTMModel, self).__init__()
        self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, output_size)

    def forward(self, x):
        out, _ = self.lstm(x) # LSTM层
        out = self.fc(out[:, -1, :]) # 全连接层
        return out
  • input_size
    : 输入特征的大小。
  • hidden_size
    : 隐藏状态的大小。
  • num_layers
    : LSTM层数。
  • output_size
    : 输出的大小。

训练模型

接下来,我们定义训练循环来训练模型。

import torch.optim as optim

# 定义超参数
input_size = 10
hidden_size = 64
num_layers = 1
output_size = 1
learning_rate = 0.001
epochs = 100

# 创建模型实例
model = LSTMModel(input_size, hidden_size, num_layers, output_size)

# 定义损失函数和优化器
loss_function = nn.MSELoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)

# 训练循环
for epoch in range(epochs):
    outputs = model(inputs)
    optimizer.zero_grad()
    loss = loss_function(outputs, targets)
    loss.backward()
    optimizer.step()
    print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item()}')

这里,我们使用均方误差损失,并通过Adam优化器来训练模型。

评估和预测

训练完成后,我们可以使用模型进行预测,并评估其在测试数据上的性能。

# 在测试数据上进行评估
model.eval()
with torch.no_grad():
    predictions = model(test_inputs)
    # ... 进一步评估预测 ...

file

5. LSTM总结

长短时记忆网络(LSTM)自从被提出以来,已经成为深度学习和人工智能领域的一个重要组成部分。以下是关于LSTM的一些关键要点的总结:

解决长期依赖问题

LSTM通过其独特的结构和门控机制,成功解决了传统RNNs在处理长期依赖时遇到的挑战。这使得LSTM在许多涉及序列数据的任务中都表现出色。

广泛的应用领域

从自然语言处理到金融预测,从音乐生成到医疗分析,LSTM的应用领域广泛且多样。

灵活与强大

LSTM不仅可以单独使用,还可以与其他神经网络架构(如CNN、Transformer等)结合,创造更强大、更灵活的模型。

开源支持

流行的深度学习框架如TensorFlow和PyTorch都提供了易于使用的LSTM实现,促进了研究和开发的便利性。

持战与展望

虽然LSTM非常强大,但也有其持战和局限性,例如计算开销和超参数调整。新的研究和技术进展可能会解决这些持战或提供替代方案,例如GRU等。

总结反思

LSTM的出现推动了序列建模和时间序列分析的前沿发展,使我们能够解决以前难以处理的问题。作为深度学习工具箱中的一个关键组件,LSTM为学者、研究人员和工程师提供了强大的工具来解读和预测世界的复杂动态。

关注TechLead,分享AI与云服务技术的全维度知识。作者拥有10+年互联网服务架构、AI产品研发经验、团队管理经验,同济本复旦硕,复旦机器人智能实验室成员,阿里云认证的资深架构师,项目管理专业人士,上亿营收AI产品研发负责人。
如有帮助,请多关注
TeahLead KrisChang,10+年的互联网和人工智能从业经验,10年+技术和业务团队管理经验,同济软件工程本科,复旦工程管理硕士,阿里云认证云服务资深架构师,上亿营收AI产品业务负责人。

本文分享自华为云社区《
GuassDB数据库的GRANT & REVOKE
》,作者: Gauss松鼠会小助手2 。

一、GaussDB的权限概述

在数据库中,对象的创建者将成为该对象的所有者,具有对该对象进行查询、修改和删除等操作的权限。同时,系统管理员也拥有与所有者相同的权限。因此,如果要让其他用户能够使用某个对象,必须向该用户或包含该用户的角色授予必要的权限。

GaussDB数据库对象权限:

对象

权限

说明

数据库 DATABASE

CONNECT

允许用户连接到指定的数据库

CREATE

允许在数据库里创建新的模式

模式 SCHEMA

CREATE

允许在模式中创建新的对象

USAGE

允许访问包含在指定模式中的对象,若没有该权限,则只能看到这些对象的名字

函数 FUNCTION

EXECUTE

允许使用指定的函数,以及利用这些函数实现的操作符

表空间 TABLESPACE

CREATE

允许在表空间中创建表,允许在创建数据库和模式的时候把该表空间指定为缺省表空间。

表 TABLE

INSERT

DELETE

UPDATE

SELECT

允许用户对指定表进行增删改查操作

TRUNCATE

允许执行TRUNCATE语句删除指定表中的所有记录。

REFERENCES

创建一个外键约束,必须拥有参考表和被参考表的REFERENCES权限

要撤消已经授予的权限,可以使用
REVOKE。

对象所有者的权限(例如ALTER、DROP、COMMENT、INDEX、VACUUM、GRANT和REVOKE)是隐式拥有的,即只要拥有对象就可以执行对象所有者的这些隐式权限。对象所有者可以撤消自己的普通权限。

系统表和系统视图要么只对系统管理员可见,要么对所有用户可见。标识了需要系统管理员权限的系统表和视图只有系统管理员可以查询。

数据库提供对象隔离的特性,对象隔离特性开启时,用户只能查看有权限访问的对象(表、视图、字段、函数),系统管理员不受影响。

不建议用户修改系统表和系统视图的权限。

二、GaussDB权限设计建议

在进行业务使用前,必须由系统管理员(root用户)创建数据库、模式(SCHEMA)和用户(USER)。然后,需要为相关用户授予访问对象所需的权限。如果该用户不是该模式的所有者,则要访问该模式下的对象,还需要同时向该用户授予模式的usage权限和对象的相应权限。

DATABASE、SCHEMA和USER名使用小写。数据库会默认把其名转为小写,连接串里面如果出现大写的对象名无法连接到数据库。

对角色和用户赋权时,应使用最小化权限原则。

优先通过角色来管理权限。使用角色管理权限,再将角色赋予用户。例如:

  • 角色和用户为多对多关系,一个角色可以赋予多个用户,修改角色中的权限,被赋予角色的用户权限就可以同时更新。
  • 删除用户时,不会影响到角色。
  • 新建用户后可以通过赋予角色快速获取所需权限。

在删除指定数据库时,应回收用户对该数据库的CONNECT权限,避免删除时仍然存在活跃的数据库连接而失败。

三、GaussDB的GRANT命令

1.功能说明

1)
将系统权限授权给角色或用户

系统权限又称为用户属性,包括SYSADMIN、CREATEDB、CREATEROLE、AUDITADMIN、MONADMIN、OPRADMIN、POLADMIN、INHERIT、REPLICATION、VCADMIN和LOGIN等。

系统权限一般通过CREATE/ALTER ROLE语法来指定。其中,SYSADMIN权限可以通过GRANT/REVOKE ALL PRIVILEGE授予或撤销。但系统权限无法通过ROLE和USER的权限被继承,也无法授予PUBLIC。

2)
将数据库对象授权给角色或用户

将数据库对象(表和视图、指定字段、数据库、函数、模式、表空间等)的相关权限授予特定角色或用户;

GRANT命令将数据库对象的特定权限授予一个或多个角色。这些权限会追加到已有的权限上。

关键字PUBLIC表示该权限要赋予所有角色,包括以后创建的用户。PUBLIC可以看做是一个隐含定义好的组,它总是包括所有角色。任何角色或用户都将拥有通过GRANT直接赋予的权限和所属的权限,再加上PUBLIC的权限。

如果声明了
WITH GRANT OPTION,则被授权的用户也可以将此权限赋予他人。这个选项不能赋予PUBLIC(GaussDB特有的属性)。

GaussDB会将某些类型的对象上的权限授予PUBLIC。默认情况下,对表、表字段、序列、外部数据源、外部服务器、模式或表空间对象的权限不会授予PUBLIC,而以下这些对象的权限会授予PUBLIC:数据库的CONNECT权限和CREATE TEMP TABLE权限、函数的EXECUTE特权、语言和数据类型(包括域)的USAGE特权。当然,对象拥有者可以撤销默认授予PUBLIC的权限并专门授予权限给其他用户。为了更安全,建议在同一个事务中创建对象并设置权限,这样其他用户就没有时间窗口使用该对象。

对象的所有者缺省具有该对象上的所有权限,出于安全考虑所有者可以舍弃部分权限,但ALTER、DROP、COMMENT、INDEX、VACUUM以及对象的可再授予权限属于所有者固有的权限,隐式拥有。

3)
将角色或用户的权限授权给其他角色或用户

将一个角色或用户的权限授予一个或多个其他角色或用户。在这种情况下,每个角色或用户都可视为拥有一个或多个数据库权限的集合。

如果声明了
WITH ADMIN OPTION,被授权的用户可以将该权限再次授予其他角色或用户,以及撤销所有由该角色或用户继承到的权限。当授权的角色或用户发生变更或被撤销时,所有继承该角色或用户权限的用户拥有的权限都会随之发生变更。

数据库系统管理员可以给任何角色或用户授予/撤销任何权限。拥有CREATEROLE权限的角色可以赋予或者撤销任何非系统管理员角色的权限。

4)
将ANY权限授予给角色或用户

将ANY权限授予特定的角色和用户。当声明了WITH ADMIN OPTION,被授权的用户可以将该ANY权限再次授予其他角色/用户,或从其他角色/用户处回收该ANY权限。ANY权限可以通过角色被继承,但不能赋予PUBLIC。初始用户和三权分立关闭时的系统管理员用户可以给任何角色/用户授予或撤销ANY权限。

目前支持以下ANY权限:

CREATE ANY TABLE

CREATE ANY SEQUENCE

ALTER ANY TABLE

CREATE ANY INDEX

DROP ANY TABLE

CREATE ANY FUNCTION

SELECT ANY TABLE

EXECUTE ANY FUNCTION

INSERT ANY TABLE

CREATE ANY PACKAGE

UPDATE ANY TABLE

EXECUTE ANY PACKAGE

DELETE ANY TABLE

CREATE ANY TYPE

2.注意事项

1)不允许将ANY权限授予PUBLIC,也不允许从PUBLIC回收ANY权限。

2)ANY权限属于数据库内的权限,只对授予该权限的数据库内的对象有效,例如SELECT ANY TABLE只允许用户查看当前数据库内的所有用户表数据,对其他数据库内的用户表无查看权限。

3)即使用户被授予ANY权限,也不能对私有用户下的对象进行访问操作(INSERT、DELETE、UPDATE、SELECT)。

4)ANY权限与原有的权限相互无影响。

5)如果用户被授予CREATE ANY TABLE权限,在同名schema下创建表的属主是该schema的创建者,用户对表进行其他操作时,需要授予相应的操作权限。

6)需要谨慎授予用户CREATE ANY FUNMCTION的权限,以免其他用户利用SECURITY DEFINER类型的函数进行权限提升。

3.常用语法

1)将表或视图的访问权限赋予指定的用户或角色

GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | ALTER | DROP | COMMENT | INDEX |VACUUM } [, ...]|ALL [ PRIVILEGES ] }

ON { [ TABLE ] table_name [, ...]
|ALL TABLES IN SCHEMA schema_name [, ...] }

TO { [ GROUP ] role_name
|PUBLIC } [, ...]

[ WITH GRANT OPTION ];

2)将表中字段的访问权限赋予指定的用户或角色

GRANT { {{ SELECT | INSERT | UPDATE | REFERENCES |COMMENT } ( column_name [, ...] )} [, ...]|ALL [ PRIVILEGES ] ( column_name [, ...] ) }

ON [ TABLE ] table_name [, ...]

TO { [ GROUP ] role_name
|PUBLIC } [, ...]

[ WITH GRANT OPTION ];

3)将数据库的访问权限赋予指定的用户或角色

GRANT { { CREATE | CONNECT | TEMPORARY | TEMP | ALTER | DROP |COMMENT } [, ...]|ALL [ PRIVILEGES ] }

ON DATABASE database_name [, ...]

TO { [ GROUP ] role_name
|PUBLIC } [, ...]

[ WITH GRANT OPTION ];

4)将函数的访问权限赋予给指定的用户或角色

GRANT { { EXECUTE | ALTER | DROP | COMMENT } [, ...] |ALL [ PRIVILEGES ] }

ON { FUNCTION {function_name ( [ {[ argmode ] [ arg_name ] arg_type} [, ...] ] )} [, ...]
|ALL FUNCTIONS IN SCHEMA schema_name [, ...] }

TO { [ GROUP ] role_name
|PUBLIC } [, ...]

[ WITH GRANT OPTION ];

5)将存储过程的访问权限赋予给指定的用户或角色

GRANT { { EXECUTE | ALTER | DROP | COMMENT } [, ...] |ALL [ PRIVILEGES ] }

ON { PROCEDURE {proc_name ( [ {[ argmode ] [ arg_name ] arg_type} [, ...] ] )} [, ...]

TO { [ GROUP ] role_name
|PUBLIC } [, ...]

[ WITH GRANT OPTION ];

……

四、GaussDB的REVOKE命令用法

1.功能说明

REVOKE用于撤销一个或多个用户或角色的权限。

2.注意事项

非对象所有者REVOKE权限时,按照以下规则执行:

1)如果授权用户没有该对象上的权限,则命令立即失败。

2)如果授权用户有部分权限,则只撤销那些有授权选项的权限。

3)如果授权用户没有授权选项,REVOKE ALL PRIVILEGES形式将发出一个错误信息,而对于其他形式的命令而言,如果是命令中指定名称的权限没有相应的授权选项,该命令将发出一个警告。

3.常用语法

1)回收指定表或视图上的权限

REVOKE [ GRANT OPTION FOR ]

{ { SELECT
| INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | ALTER | DROP | COMMENT | INDEX |VACUUM }[, ...]|ALL [ PRIVILEGES ] }

ON { [ TABLE ] table_name [, ...]
|ALL TABLES IN SCHEMA schema_name [, ...] }

FROM { [ GROUP ] role_name
|PUBLIC } [, ...]

[ CASCADE
| RESTRICT ];

2)回收表上指定字段的权限

REVOKE [ GRANT OPTION FOR ]

{ {{ SELECT
| INSERT | UPDATE | REFERENCES |COMMENT } ( column_name [, ...] )}[, ...]|ALL [ PRIVILEGES ] ( column_name [, ...] ) }

ON [ TABLE ] table_name [, ...]

FROM { [ GROUP ] role_name
|PUBLIC } [, ...]

[ CASCADE
| RESTRICT ];

3)回收指定数据库上的权限

REVOKE [ GRANT OPTION FOR ]

{ { CREATE
| CONNECT | TEMPORARY | TEMP | ALTER | DROP |COMMENT } [, ...]|ALL [ PRIVILEGES ] }

ON DATABASE database_name [, ...]

FROM { [ GROUP ] role_name
|PUBLIC } [, ...]

[ CASCADE
| RESTRICT ];

4)回收指定函数上的权限

REVOKE [ GRANT OPTION FOR ]

{ { EXECUTE
| ALTER | DROP | COMMENT } [, ...] |ALL [ PRIVILEGES ] }

ON { FUNCTION {function_name ( [ {[ argmode ] [ arg_name ] arg_type} [, ...] ] )} [, ...]
|ALL FUNCTIONS IN SCHEMA schema_name [, ...] }

FROM { [ GROUP ] role_name
|PUBLIC } [, ...]

[ CASCADE
| RESTRICT ];

5)回收指定存储过程上的权限

REVOKE [ GRANT OPTION FOR ]

{ { EXECUTE
| ALTER | DROP | COMMENT } [, ...] |ALL [ PRIVILEGES ] }

ON { PROCEDURE {proc_name ( [ {[ argmode ] [ arg_name ] arg_type} [, ...] ] )} [, ...]
|ALL PROCEDURE IN SCHEMA schema_name [, ...] }

FROM { [ GROUP ] role_name
|PUBLIC } [, ...]

[ CASCADE
| RESTRICT ];

……

五、GaussDB示例

1.GRANT 语句示例

1)授予用户 user_name 对 database_name.table_name 表的 SELECT、INSERT、UPDATE、DELETE 权限。

GRANT SELECT,INSERT,UPDATE,DELETE ON database_name.table_name TO user_name;

2)授予用户 user_name 对 database_name.table_name 的所有权限。

GRANT ALL PRIVILEGES ON database_name.table_name TO user_name;

3)授予用户 user_name 对 database_name.table_name 的 SELECT、INSERT、UPDATE、DELETE 权限,并允许他将该权限传递给其他用户。

GRANT SELECT,INSERT,UPDATE,DELETE ON database_name.table_name TO user_name WITH GRANT OPTION;

2.REVOKE 语句示例:

1)撤销用户 user_name 对 database_name.table_name 表的 SELECT、INSERT、UPDATE、DELETE 权限。

REVOKE SELECT,INSERT,UPDATE,DELETE on database_name.table_name FROM user_name;

2)撤销用户 user_name 对 database_name.table_name 的所有权限。

REVOKE ALL PRIVILEGES ON database_name.table_name FROM user_name;

3)撤销用户 user_name 对 database_name.table_name 表的 SELECT、INSERT、UPDATE、DELETE 权限。

Tip:一个用户只能撤销由它自己直接赋予的权限,依赖性权限仍然存在,但如果声明了CASCADE,则所有依赖性权限都被撤销.

REVOKE SELECT,INSERT,UPDATE,DELETE ON database_name.table_name FROM user_name WITH GRANT OPTION;

小结
:数据库的GRANT & REVOKE命令是用于管理数据库用户权限的命令。这些命令通常用于在数据库中为用户分配权限,以便用户可以访问和操作数据库中的数据。GRANT & REVOKE是GaussDB云数据库中非常重要的一个命令,它可以用于撤销和管理数据库中的不同对象的访问权限,从而保证数据库的安全性和可靠性。

点击关注,第一时间了解华为云新鲜技术~

深搜(DFS)与广搜(BFS)

在查找二叉树某个节点时,如果把二叉树所有节点理理解为解空间,待找到那个节点理解为满足特定条件的解,对此解答可以抽象描述为:
在解空间中搜索满足特定条件的解
,这其实就是搜索算法(Search)的一种描述。当然也有其他描述,比如是“指一类用于在数据集合中查找特定项或解决问题的算法”,又或者是“指通过按照一定规则逐一检查数据,以找到所需的信息或解决特定的问题。”等等。

搜索算法在计算机科学和信息检索中具有广泛的应用,包括搜索引擎、数据库查询、排序、路径规划、机器学习和人工智能等领域。其中最基础之一的搜索算法就是 深度优先搜索(Depth First search,简称 DFS)和广度优先搜索(Breadth First Search,简称 BFS)。

PS:因发明“深度优先搜索算法”,约翰·霍普克洛夫特 与 罗伯特·塔扬在1986年共同获得计算机领域的最高奖图灵奖

在写这两种算法之前,先看几个数据结构。

队列(Queue)、栈(Stack)

排队
相信是日常生活中购物时可能遇到的情况,其中最重要的一个原则就是先来的先买。同样的,可以把类似这种规则应用在数据结构上,那么这种数据结构就是队列(Queue):是一种线性数据结构,遵循先进先出(First-In-First-Out,FIFO)的原则。

(PS:什么叫线性数据?指一种数据元素的有序集合,其中元素之间存在线性(有序)关系。)

其两个基本的操作:

  • 入队(Enqueue): 向队列的末尾添加一个新元素。这个操作将新元素排队等待被处理。通常,它是队列中元素的最后一个操作。
  • 出队(Dequeue): 从队列的前端移除一个元素,并返回它。这个操作模拟了第一个等待的元素被处理的情况。通常,出队操作是队列中元素的第一个操作。

如果把队列遵循的原则进行修改为后进先出,这样就演变出另外一种数据结构 栈(Stack):是一种线性数据结构,它遵循先进后出(Last-In-First-Out,LIFO)的原则。

同样类似队列两个基本操作:

  • 入栈(Push): 向栈顶添加一个新元素。
  • 出栈(Pop): 从栈顶移除元素。

PS:栈顶(Top)是当前位于栈的顶部的元素,也是栈中唯一一个可见的元素。

LeetCode 20. 有效的括号【简单】

给定一个只包括 '(',')','{','}','','' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。
  • 左括号必须以正确的顺序闭合。
  • 每个右括号都有一个对应的相同类型的左括号。

双端队列(Double-Ended Queue,简称 Deque)

如果要一个数据结构即支持队列的操作也支持栈的操作,双端队列(Double-Ended Queue,简称Deque)是这样一种线性数据结构,它具有队列和栈的特性,允许在队列的两端执行插入和删除操作。双端队列支持元素的快速插入和删除,无论是在队列的前端(头部)还是后端(尾部),因此它被称为"双端",即有两个端点。

双端队列的存储实现上既可以 是链表,也可以是 数组;可以根据实际情况进行选择。

		// java 示例代码
        Deque<Integer> dequeList = new LinkedList<>();
        Deque<Integer> dequeArray = new ArrayDeque<>();

PS:由于双端队列能够覆盖 栈、队列两者的操作,使用Java解决算法题时,如需使用栈(Stack)、队列(Queue)情况 经常都会使用 Deque 来完成。

深度搜索(Depth-First Search,DFS)中的"深度"指的是在搜索问题的解空间时,算法首先沿着一条路径深入到解空间中,直到达到最深处或者无法再深入为止;然后再回退并继续探索下一个分支。

虽然 在上一篇
二叉树
中没提及这个名称,但其实上篇涉及的几个算法问题解法都是深度搜索;DFS通常使用递归或栈(堆栈)数据结构来实现,在这里不妨再练习一题。

LeetCode 113. 路径总和 II 【中等】

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。

广度搜索(Breadth-First Search,BFS)中的"广度"指的是算法在搜索问题的解空间时,从起始点开始逐层地向外扩展,以确保先探索当前层的所有节点,然后再深入到下一层的节点,层层展开。

所谓“层层展开” 例如在二叉树结构中,根节点是第0层,子节点是第1层,孙子节点是第2层,依此类推。BFS通常使用队列数据结构来实现。

LeetCode 515. 在每个树行中找最大值【中等】

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

LeetCode 695. 岛屿的最大面积【中等】

给你一个大小为 m x n 的二进制矩阵 grid 。
岛屿 是由一些相邻的 1 (代表土地) 构成的组合,这里的「相邻」要求两个 1 必须在 水平或者竖直的四个方向上 相邻。你可以假设 grid 的四个边缘都被 0(代表水)包围着。
岛屿的面积是岛上值为 1 的单元格的数目。计算并返回 grid 中最大的岛屿面积。如果没有岛屿,则返回面积为 0 。


总结下

  • 队列(Queue)、栈(Stack)数据结构开始,引出到 双端队列(Double-Ended Queue);
  • 深度搜索(Depth-First Search)的基本应用,通常使用递归或栈(堆栈)数据结构来实现;
  • 广度优先搜索(Breadth First Search)的基本应用,通常使用队列数据结构来实现。

背景:

目前,大模型的发展已经非常火热,关于大模型的训练、微调也是各个公司重点关注方向。但是大模型训练的痛点是模型参数过大,动辄上百亿,如果单靠单个GPU来完成训练基本不可能。所以需要多卡或者分布式训练来完成这项工作。

一、分布式训练

1.1 目前主流的大模型分布式训练主要包括两种:

  • 数据并行训练
  • 模型并行训练

二、DeepSpeed

DeepSpeed是由Microsoft提供的分布式训练工具,旨在支持更大规模的模型和提供更多的优化策略和工具。对于更大模型的训练来说,DeepSpeed提供了更多策略,例如:Zero、Offload等。

2.1 基础组件

分布式训练需要掌握分布式环境中的基础配置,包括节点变化、全局进程编号、局部进程编号、全局总进程数、主节点等。这些组件都跟分布式训练紧密相关,同时组件之间也有非常大的联系,例如通信联系等。

2.2 通信策略

既然是分布式训练,那机器之间必须要保持通信,这样才可以传输模型参数,梯度参数等信息。

DeepSpeed提供了mpi、gioo、nccl等通信策略

通信策略 通信作用
mpi 它是一种跨界点的通信库,经常用于CPU集群的分布式训练
gloo 它是一种高性能的分布式训练框架,可以支持CPU或者GPU的分布式训练
nccl 它是nvidia提供的GPU专用通信库,广泛用于GPU上的分布式训练

我们在使用DeepSpeed进行分布式训练的时候,可以根据自身的情况选择合适的通信库,通常情况下,如果是GPU进行分布式训练,可以选择nccl。

2.3 Zero(零冗余优化器)

Microsoft开发的Zero可以解决分布式训练过程中数据并行和模型并行的限制。比如: Zero通过在数据并行过程中划分模型状态(优化器、梯度、参数),来解决数据并行成可能出现内存冗余的情况(正常数据并行训练,模型全部参数是复制在各个机器上的);同时可以在训练期间使用动态通信计划,在分布式设备之间共享重要的状态变量,这样保持计算粒度和数据并行的通信量。

Zero是用于大规模模型训练优化的技术,它的主要目的是减少模型的内存占用,让模型可以在显卡上训练,内存占用主要分为
Model States

Activation
两个部分,Zero主要解决的是Model States的内存占用问题。

Zero将模型参数分成三个部分:

状态 作用
Optimizer States 优化器在进行梯度更新的时候需要用到的数据
Gradient 在反向转播过程中产生的数据,其决定参数的更新方向
Model Parameter 模型参数,在模型训练过程中通过数据“学习”的信息

Zero的级别如下:

级别 作用
Zero-0 不使用所有类型的分片,仅使用DeepSpeed作为DDP
Zero-1 分割Optimizer States, 减少4倍内存,通信容量和数据并行性相同
Zero-2 分割Optimizer States和Gradients,减少8倍内存,通信容量和数据并行性相同
Zero-3 分割Optimizer States、gradients、Parametes,内存减少与数据并行度呈线性关系。例如,在64个GPU(Nd=64)之间进行拆分将产生64倍的内存缩减。通信量有50%的适度增长
Zero-Infinity Zero-Infinity是Zero-3的扩展,它允许通过使用 NVMe 固态硬盘扩展 GPU 和 CPU 内存来训练大型模型

2.4 Zero-Offload:

相比GPU,CPU就相对比较廉价,所以Zero-Offload思想是将训练阶段的某些模型状态放(offload)到内存以及CPU计算。

Zero-Offload不希望为了最小化显存占用而让系统计算效率下降,但如果使用CPU也需要考虑通信和计算的问题(通信:GPU和CPU的通信;计算:CPU占用过多计算就会导致效率降低)。

Zero-Offload想做的是把计算节点和数据节点分布在GPU和CPU上,计算节点落到哪个设备上,哪个设备就执行计算,数据节点落到哪个设备上,哪个设备就负责存储。

Zero-Offload切分思路:

下图中有四个计算类节点:FWD、BWD、Param update和float2half,前两个计算复杂度大致是 O(MB), B是batch size,后两个计算复杂度是 O(M)。为了不降低计算效率,将前两个节点放在GPU,后两个节点不但计算量小还需要和Adam状态打交道,所以放在CPU上,Adam状态自然也放在内存中,为了简化数据图,将前两个节点融合成一个节点FWD-BWD Super Node,将后两个节点融合成一个节点Update Super Node。如下图右边所示,沿着gradient 16和parameter 16两条边切分。

Zero-Offload计算思路:

在GPU上面进行前向和后向计算,将梯度传给CPU,进行参数更新,再将更新后的参数传给GPU。为了提高效率,可以将计算和通信并行起来,GPU在反向传播阶段,可以待梯度值填满bucket后,一遍计算新的梯度一遍将bucket传输给CPU,当反向传播结束,CPU基本上已经有最新的梯度值了,同样的,CPU在参数更新时也同步将已经计算好的参数传给GPU,如下图所示。

2.5 混合精度:

混合精度训练是指在训练过程中同时使用FP16(半精度浮点数)和FP32(单精度浮点数)两种精度的技术。使用FP16可以大大减少内存占用,从而可以训练更大规模的模型。但是,由于FP16的精度较低,训练过程中可能会出现梯度消失和模型坍塌等问题。

DeepSpeed支持混合精度的训练,可以在config.json配置文件中设置来启动混合精度("fp16.enabled":true)。在训练的过程中,DeepSpeed会自动将一部分操作转化为FP16格式,并根据需要动态调整精度缩放因子,来保证训练的稳定性和精度。

在使用混合精度训练时,需要注意一些问题,例如梯度裁剪(Gradient Clipping)和学习率调整(Learning Rate Schedule)等。梯度裁剪可以防止梯度爆炸,学习率调整可以帮助模型更好地收敛。

三、总结

DeepSpeed方便了我们在机器有限的情况下来训练、微调大模型,同时它也有很多优秀的性能来使用,后期可以继续挖掘。

目前主流的达模型训练方式: GPU + PyTorch + Megatron-LM + DeepSpeed

优势

  1. 存储效率
    :DeepSpeed提供了一种Zero的新型解决方案来减少训练显存的占用,它与传统的数据并行不同,它将模型状态和梯度进行分区来节省大量的显存;
  2. 可扩展性
    :DeepSpeed支持高效的数据并行、模型并行、pipeline并行以及它们的组合,这里也称3D并行;
  3. 易用性:
    在训练阶段,只需要修改几行代码就可以使pytorch模型使用DeepSpeed和Zero。

参考:

1.
http://wed.xjx100.cn/news/204072.html?action=onClick

2.
https://zhuanlan.zhihu.com/p/513571706

作者:京东物流 郑少强

来源:京东云开发者社区 转载请注明来源