基于 SmartX 分布式存储的 iSCSI 与两种 NVMe-oF 技术与性能对比
作者:深耕行业的 SmartX 金融团队
本文重点
SmartX 分布式块存储 ZBS 提供 2 种存算分离架构下的数据接入协议,分别是 iSCSI 和 NVMe-oF。其中,iSCSI 虽然具有很多优势,但不适合支持高性能的工作负载,这也是 SmartX 选择支持 NVMe-oF 的原因之一。
结合性能和网络条件这两个角度的考虑,ZBS 选择支持 NVMe over RDMA/RoCE v2 和 NVMe over TCP,以满足用户的多种需求。
ZBS 中,NVMe-oF 接入采用继承策略和均衡策略,这样的设计可以在充分利用多个存储接入点的同时避免占用所有存储接入点的处理能力,保持各个接入点的负载基本均衡。
从实验室基础性能验证和金融用户性能验证可以看出,相比 iSCSI 和 NVMe over TCP,使用 NVMe over RDMA 作为接入协议,可以取得较高的 I/O 性能输出,具体表现为更高的随机 IOPS 和顺序带宽,以及更低的延时表现。
1 背景
“分布式块存储 ZBS 的自主研发之旅|架构篇”文章提及了部分数据路径的设计实现,仅描述了当 I/O 发生时,Access 数据接入组件与 Meta 管理组件之间的通信过程,该过程属于整个 I/O 路径的后半段。
本篇文章,我们将详细介绍数据接入路径中的前半段,即计算端与 ZBS 通信的接入协议层,使读者可以更加全面地了解 ZBS 分布式存储接入协议,同时通过对比不同接入协议的原理实现、基础环境要求和性能测试数据,为客户在部署使用 ZBS,提供最佳实践参考。
本篇文章会涉及到 RDMA(Remote Direct Memory Access)技术,如果读者想更多地了解该技术细节,推荐阅读“分布式块存储 ZBS 的自主研发之旅|数据同步协议RDMA”文章。
2 Access 概述
Access 是虚拟存储对象(File/LUN/Namespace)与实际的数据块(Extent)之间的交互边界。Access 接收 NFS Client、iSCSI Initiator、NVMF initiator 的读写请求,并将不同的协议对象,例如 File、LUN、Namespace 转义成 ZBS 内部的 Volume 与 Extent 对象,并处理数据多副本等 ZBS 内部逻辑。
Access 通过 Session 机制与 Meta 建立联系,并由 Session 确保数据访问权限(Extent Lease)的唯一性。

图 1:Access 接入服务
3 接入协议
目前 ZBS 提供 4 种接入协议,分别是 NFS、iSCSI、NVMe-oF 和 vHost,其中 NFS 和 vHost 主要应用场景是超融合架构(相关 vHost 详细介绍可参考文章 “SPDK vHost-user 如何帮助超融合架构实现 I/O 存储性能提升”),本文不进行过多展开,将主要介绍存算分离架构下的数据接入协议。

图 2:ZBS iSCSI & NVMe-oF 接入协议
3.1 ZBS iSCSI 实现
当前,在云计算块存储场景中,iSCSI 依然是分布式存储 SDS 主流的接入方法之一,其基于标准的 TCP/IP 协议栈、无需改动已有客户端系统、对服务器硬件和标准以太网有着广泛的兼容性、管理简单等特点,使 iSCSI 得到广泛的应用。
iSCSI 是目前 ZBS 支持的接入协议之一,在 ZBS 实现中,客户端(initiator)均不直接指向某个具体的存储节点 Access 作为协议接入端,而是指向 iSCSI Redirector 服务地址。当 iSCSI initiator 向 iSCSI Redirector 发起 Login 请求时,iSCSI Redirector 将登录请求转发给 Meta,Meta 根据与 Access 维护的 Session 信息寻找是否已经存在绑定的 Access Server,如有则返回对应的 Access Server 地址,否则将返回任一 Access Server 地址。客户端(initiator)将与对应的 Access Server 完成 Login 过程与后续的 I/O 处理流程。
通过 Redirector 服务可简化 iSCSI 接入高可用配置的复杂度。同样,iSCSI 也基于 Redirector 服务提供单一客户端(initiator)访问一个 iSCSI Target 仅使用一条数据链路的单点接入保证(避免同一 Target 的多点访问),以及接入链路均衡的作用。

图 3 :iSCSI 接入架构
iSCSI 虽然具备很多使用上的优势,但是在性能层面,却一直存在难以充分发挥现代高速存储和网络设备性能的问题,SCSI 协议的设计和开发时间可以追溯到上个世纪,首先是当时硬件环境还是以机械磁盘为主流,协议对当今高性能硬件,例如 NVMe 介质,以及现代工作负载的要求,已显疲态。其次是协议栈层面,长期不断的开发迭代,相较新型的协议,iSCSI 相对厚重且效率低下。
对于性能提升,iSER(iSCSI Extensions for RDMA)是 iSCSI 的一次进化,通过 RDMA 能力,来提升 iSCSI 在网络层的性能。ZBS 并没有采用这样的技术栈,原因也很简单,因为 iSER 的基石依然是 iSCSI,前面也简要分析了该协议的一些不足,做个比喻,就是建筑物和地基的关系。既然要使用 RDMA,选择新型的 NVMe 协议支撑高性能的工作负载会是更优的选择。
3.2 NVMe-oF 介绍
在介绍 NVMe-oF 之前,首先简单介绍一下 NVM Express(NVMe)协议规范,该协议定义主机如何通过 PCIe 总线与非易失性存储器进行通信。NVMe 规范是为 SSD 高速存储介质而量身设计,相较于 SCSI,是一种更加高效的接口规范,支持 65535 个 I/O 队列,每个队列支持 65535 条命令(队列深度)。队列映射提供预期的 CPU 资源调度,并能适应在中断或轮询模式下的设备驱动,提供了更高的数据吞吐和更低的通信延迟。
更快的存储,则需要更快的网络才能发挥最大的存储价值。NVMe-oF 全称是 NVMe over Fabrics(本文均采用缩写 NVMe-oF),它把 NVMe 在单系统内部提供的高性能、低延迟和极低的协议开销等优势进一步发挥到客户端与存储系统互联的网络结构当中。NVMe-oF 定义了使用多种通用的传输层协议来实现 NVMe 远程连接能力。

图 4:NVMe over Fabrics
NVMe-oF 承载网络(数据平面)包括:
(1)NVMe over FC:基于传统的 FC 网络(主机总线适配器 HBA 和光纤交换机构建的专有通信网络),与 FC-SAN(SCSI)可以同时运行在同一个 FC 网络中,最大化地复用 FC 网络基础环境,发挥 NVMe 新型协议的优势。常用于传统集中存储的升级改造。
(2)NVMe over RDMA:通过远程直接内存访问技术,允许客户端程序远程访问存储系统的内存空间进行数据传输。具有数据零拷贝(不涉及网络堆栈执行数据传输)、Kernel Bypass(应用程序可以直接从用户空间执行数据传输,无需内核参与)、减少 CPU 资源消耗(应用程序可以访问远程内存,而无需在远程服务器中消耗任何 CPU Cycle)等特点。
① InfiniBand - 通过 InfiniBand 网络使用 RDMA,在高性能计算 HPC 领域非常流行,与 FC 相似,需要专有的网络适配器和交换网络支撑。
② RoCE - 全称 RDMA over Converged Ethernet,即通过以太网实现 RDMA,目前有两个版本:RoCEv1 不可路由,仅可以在 2 层工作;RoCEv2 使用 UDP/IP,具有 3 层路由能力。

图 5:RoCEv1/v2 帧结构(来自 Wikipedia)
③ iWARP - 构建在 TCP/IP 之上。跟 RoCE 协议继承自 Infiniband 不同,iWARP 本身不是直接从 Infiniband 发展而来的。Infiniband 和 RoCE 协议都是基于 “Infiniband Architecture Specification”,也就是常说的“IB 规范”。而 iWARP 是自成一派,遵循着一套 IETF 设计的协议标准。虽然遵循着不同的标准,但是 iWARP 的设计思想受到了很多 Infiniband 的影响,并且目前使用同一套编程接口。
(3)NVMe over TCP:与前两种实现方式不同,该方案无需任何特殊的硬件要求,基于通用标准以太网环境。成本低是该协议的优势,缺点是需要更多的 CPU 资源参与数据处理,受限于 TCP/IP 协议,在数据传输中相对 RDMA 会引入更多的延迟。
ZBS 不支持 FC 和 IB 的主要原因是其依赖专有网络,这与 ZBS 的产品定位相冲突(基于标准以太网构建分布式存储网络)。而不支持 iWARP 原因是对比 RoCE 来看(这是一个二选一问题),在生态、协议效率和复杂度等多方面因素评估下,SmartX 更加看好 RoCE 未来的发展,在极致的性能诉求下,RoCE 也会比 iWARP 具有更强的潜力。当然,RoCE 在数据重传和拥塞控制上受限于协议,需要无损网络的环境(RoCE 对于丢包 PSN 的 NACK 重传机制,性能非常差)。这样的客观条件,是任何一个存储厂家需要结合自身产品权衡的选择题。
总结一下,应用 NVMe-oF,可以选择的技术路线有 3 条,分别是 FC、RDMA 和 TCP,从性能和网络条件这两个维度出发,ZBS 选择支持 RDMA/RoCE v2 和 TCP,这样的组合,可以非常好地适配不同客户的个性需求。
对性能敏感,并愿意为提高性能而投入更多的网络成本,可以选择使用 RDMA/RoCE v2 接入方案。
对成本敏感或受网络条件限制,可以选择 TCP 的接入方案。
3.3 ZBS NVMe-oF 实现
NVMe-oF 在 ZBS 中支持两种形态,即 RDMA/RoCE v2 和 TCP,这两个形态区别仅体现在外部客户端使用哪种协议接入 Access,在元数据管理上并没有区别。
NVMe-oF 协议本身与 iSCSI 协议有很多相似的地方,例如客户端标识为 initiator 端,服务端为 Target 端,NVMe-oF 协议中使用与 iSCSI IQN 近似的 NQN 来作为协议通讯双方的标识等。同时,NVMe-oF 定义了 Subsystem(子系统,相当于 SCSI 体系下的 Target)和 Namespace(命名空间,类似于 SCSI 体系下的 LUN)专有标准。
相比于 iSCSI 通过 initiator + Target 的数据链路控制,NVMe-oF 可以支持 initiator + Namespace 这样更小的链路控制粒度。NVMe-oF 在路径策略选择上(协议原生支持 Multipath)是通过 ANA(Asymmetric Namespace Access)机制指定 Target 链路优先级,再由客户端结合优先级与自身的链路状态探测结果选择 I/O 具体路径。
ANA 状态包括:Optimized 最优/Non-Optimized 次优/Inaccessible 不可达/Persistent Loss 失去连接/Change 状态变更。
ZBS 会将所有的可用链路设置为 OP(最优链路)和 Non-OP(次优链路)两种状态,其他状态未发生异常或变化时由 Driver 自动标记。对于每个 initiator + Namespace 的组合,仅返回 1 个最优接入点和 2 个次优接入点。在最优接入点可用时,客户端将仅通过最优接入点访问数据,在异常时选择 2 个次优接入点中的一个进行访问(出于简化安全性处理的考虑,部署时会要求客户端配置为 AB 模式,即使 2 个次优接入点是等价的,也不会进入 AA 模式,同时从两个接入点中下发 I/O)。
ZBS 接入策略:
继承策略,同一客户端访问同一 Subsystem 中的所有 Namespace 使用同一接入点。
均衡策略,保证同一 Namespace Group 中的 Namespace 尽量使用不同接入点。
ZBS 接入点分配策略可以实现以下目标:
在客户端视角,允许利用多个存储接入点的处理能力。
在客户端视角,保证不同客户端的公平性,避免占用所有存储接入点的处理能力。
在存储接入点视角,保持各个接入点的负载基本均衡,同时又尽可能发挥多个接入点的处理能力。

图 6:NVMe-oF 接入架构
4 实验室性能验证数据
4.1 环境信息
存储集群,由 3 节点组成,安装 SMTX ZBS 5.2 OS,存储内部网络开启 RDMA ,分层存储结构,所有存储节点的硬件配置相同,节点环境信息如下:

计算端安装 CentOS 8.2 操作系统,使用 FIO 压测工具(模型 direct=1,numjobs=1,ioengine=libaio),硬件环境信息如下:

4.2 性能数据
在相同的测试环境和测试方法下,分别使用不同的接入协议进行性能验证(iSCSI、NVMe over TCP 和 NVMe over RDMA),测试基于单卷(单节点性能,测试 1 个 2 副本卷)和多卷(集群性能,对于 3 节点集群,将测试 3 个 2 副本卷)的存储基准性能(4K 随机 I/O,256K 顺序 I/O)。
4.2.1 单卷性能

4.2.2 多卷性能

4.3 测试结论
通过以上基准测试数据,可以看到,相同软硬件环境以及测试方法下,使用 NVMe over RDMA 作为接入协议,可以取得较高的 I/O 性能输出,其表现为更高的随机 IOPS 和顺序带宽,以及更低的延时表现。
5 某股份制银行性能验证数据
与实验室基准测试数据不同,用户关注的是贴合自身应用业务的真实 I/O 模型。某股份制银行性能验证要求如下:
在相同环境下,验证 iSCSI、NVMe over TCP 和 NVMe over RDMA 性能表现。
I/O 模型为 8K 和 16K 随机读写,读写比例 5 : 5。
验证写平均延迟不大于 300us 和 500us 下的 IOPS 的性能表现以及对应的 iodepth。
所有接入协议场景,分布式存储内部均开启 RDMA。
5.1 环境信息
存储集群,由 3 节点组成,安装 SMTX ZBS 5.0 OS,存储内部网络开启 RDMA ,所有存储节点的硬件配置相同,节点环境信息如下:

3 台计算端,安装 CentOS 8.4 操作系统,使用 vdbench 压测工具,硬件环境信息如下:

5.2 性能数据
在相同的测试环境和测试方法下,分别使用不同的接入协议进行性能验证(iSCSI、NVMe over TCP 和 NVMe over RDMA),测试多卷集群性能(3 节点存储集群,将测试 3 个 2 副本卷)。
5.2.1 延时 <= 300us 测试数据 IOPS(单位:K)

5.2.2 延迟 <= 500us 测试数据 IOPS(单位:K)

5.3 测试结论
通过固定写入延迟,观察在调整 iodepth 深度下不同接入协议所能发挥的 IOPS 性能。从测试结果可以看出,在 8K 和 16K 混合读写测试场景中,NVMe over RDMA 依然发挥出最高的随机 I/O 性能。
6 结论
本文详细描述 ZBS 分布式块存储的数据接入原理,同时分别介绍了所支持的多种接入协议的实现方式,以及背后的思考。通过原理介绍和实际验证数据,希望给读者一个全面的视角理解 ZBS 接入服务,为更好部署和使用 ZBS 提供参考。
参考文章:
1. RDMA over Converged Ethernet. Wikipedia.
https://en.wikipedia.org/wiki/RDMA_over_Converged_Ethernet
2. How Ethernet RDMA Protocols iWARP and RoCE Support NVMe over Fabrics.
https://www.snia.org/sites/default/files/ESF/How_Ethernet_RDMA_Protocols_Support_NVMe_over_Fabrics_Final.pdf
相关文章:

基于 SmartX 分布式存储的 iSCSI 与两种 NVMe-oF 技术与性能对比
作者:深耕行业的 SmartX 金融团队本文重点SmartX 分布式块存储 ZBS 提供 2 种存算分离架构下的数据接入协议,分别是 iSCSI 和 NVMe-oF。其中,iSCSI 虽然具有很多优势,但不适合支持高性能的工作负载,这也是 SmartX 选择…...
Anaconda 安装 Pytorch
下载Anaconda,最新版本的即可,默认安装,最好不要安装在C盘,否则后面C盘容量会很大。 安装Pytorch 打开 Anaconda Prompt ,先切换镜像源为国内清华镜像源,这样安装包的时候下载速度会快一些,也容易成功一些。 在 Anaconda Prompt 命令行依次输入以下四条命令切换到清华镜…...

从零开始使用MMSegmentation训练Segformer
从零开始使用MMSegmentation训练Segformer 写在前面:最新想要用最新的分割算法如:Segformer or SegNeXt 在自己的数据集上进行训练,但是有不是搞语义分割出身的,而且也没有系统的学过MMCV以及MMSegmentation。所以就折腾了很久&am…...

会利用信息差赚钱的人才是聪明人
毕业后找不到工作,穷到只剩下时间,大小做了20多份副业兼职,终于找到了可靠的渠道, 我是专科生,学历不好,专业拉胯。毕业后,我找了两三份工作。要么工资太低,只能交房租,…...

【机器学习】Adaboost
1.什么是Adaboost AdaBoost(adapt boost),自适应推进算法,属于Boosting方法的学习机制。是一种通过改变训练样本权重来学习多个弱分类器并进行线性结合的过程。它的自适应在于:被前一个基本分类器误分类的样本的权值会…...

深度学习神经网络基础知识(二)权重衰减、暂退法(Dropout)
专栏:神经网络复现目录 深度学习神经网络基础知识(二) 本文讲述神经网络基础知识,具体细节讲述前向传播,反向传播和计算图,同时讲解神经网络优化方法:权重衰减,Dropout等方法,最后进行Kaggle实…...
[面试直通版]网络协议面试核心之HTTP,HTTPS,DNS-DNS安全
点击->计算机网络复习的文章集<-点击 目录 典型问题: 部分现象 DNS劫持 DNS欺骗 DDoS攻击 典型问题: 什么是DNS劫持,DNS欺骗,是什么原理如何防范DNS攻击? 部分现象 错误域名解析到纠错导航页面错误域名解析…...

【OJ】A+B=X
📚Description: 数列S中有n个整数,判断S中是否存在两个数A、B,使之和等于X。 ⏳Input: 第一行为T,输入包括T组测试数据。 每组数据第一行包括两个数字n和X,第二行有n个整数,表示数列S,(1&l…...

Python实现性能自动化测试,还可以如此简单
Python实现性能自动化测试,还可以如此简单 目录:导读 一、思考❓❔ 二、基础操作🔨🔨 三、综合案例演练🔨🔨 四、总结💡💡 写在最后 一、思考❓❔ 1.什么是性能自动化测试? 性…...
Leetcode力扣秋招刷题路-0080
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 80. 删除有序数组中的重复项 II 给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长…...

Java实现JDBC工具类DbUtils的抽取及程序实现数据库的增删改操作
封装DbUtils 工具类 不知道我们发现没有,不管是对数据库进行查询,还是标准的JDBC 步骤,其开端都是先实现JDBC 的加载注册,接着是获取数据库的连接,最后都是实现关闭连接,释放资源的操作。那我们何不直接把…...

【docker】拉取镜像环境报错解决#ERROR: Get https://registry-1.docker.io/v2/
🍁博主简介 🏅云计算领域优质创作者 🏅华为云开发者社区专家博主 🏅阿里云开发者社区专家博主 💊交流社区:运维交流社区 欢迎大家的加入! 文章目录问题报错原因解决方法问题 ERROR…...

java中NumberFormat 、DecimalFormat的介绍及使用,java数字格式化,BigDecimal数字格式化
文章目录前言一、NumberFormat1、概述2、实例化方法3、货币格式化4、百分比格式化5、NumberFormat的坑5.1、不同的格式化对象处理相同数值返回结果不同问题源码分析:二、DecimalFormat1、概述2、常用方法3、字符及含义0与#的区别分组分隔符的使用“%” 将数字乘以10…...
2023什么是分销商城系统?营销,核心功能
大家好,我是你们熟悉而又陌生的好朋友梦龙,一个创业期的年轻人 分销商城是指由网络营销运营商提供的,用于协助供给商搭建、管理及运作其网络销售渠道,协助分销商获取货源渠道的平台。简单来说,就是企业应用无线裂变分…...
天翼数字生活C++客户端实习
面试C客户端实习的岗位,相对不难 面试官:实习主要做的是国产操作系统下的应用,主要做的是视频监控、安防相关的工具,具体就是一个叫做 天翼云眼的软件,目前在windows下和电视下都有对应的应用,就是现在想在…...
Java 接口
文章目录1、接口的概念2、接口的定义3、接口的使用4、接口和抽象类1、接口的概念 类是一种具体的实现体,而接口定义了一种规范(抽象方法),接口定义了某一批类所需要遵循的规范,接口不关心类内部的属性和方法的具体实现…...

【React】react-router 路由详解
🚩🚩🚩 💎个人主页: 阿选不出来 💨💨💨 💎个人简介: 一名大二在校生,学习方向前端,不定时更新自己学习道路上的一些笔记. 💨💨💨 💎目…...

DaVinci 偏好设置:系统 - 内存和 GPU
偏好设置 - 系统/内存和 GPUPreferences - System/Memory and GPU内存和 GPU Memory and GPU 选项卡提供了内存配置以及 GPU 配置的相关设置。内存配置Memory Configuration系统内存System Memory列出了所用电脑的总的可用内存。限制 Resolve 内存使用到Limit Resolve memory u…...
视频知识点(22)- 教你认清楚YUV420P和YUV420SP的真正差异在哪里
*《音视频开发》系列-总览* 前言 在视频技术领域,存在着非常多的颜色空间模型,YUV颜色空间就是其中之一。我们没有必要把所有的颜色空间都搞明白,只需要关注自己所从事的领域的常用颜色空间模型即可,同样,YUV颜色空间模型也有非常多的子类型,我们也没有必要都搞得清清楚楚…...
企业电子招标采购系统源码Spring Cloud + Spring Boot + MybatisPlus + Redis + Layui
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...

Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...

Linux-07 ubuntu 的 chrome 启动不了
文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了,报错如下四、启动不了,解决如下 总结 问题原因 在应用中可以看到chrome,但是打不开(说明:原来的ubuntu系统出问题了,这个是备用的硬盘&a…...

C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...

stm32wle5 lpuart DMA数据不接收
配置波特率9600时,需要使用外部低速晶振...