Netty EventLoopGroup 详解:Nio、Epoll、Poll 、KQueue和IoUring

Netty EventLoopGroup 详解:Nio、Epoll、Poll 、KQueue和IoUring

概述

Netty 是一个高性能的网络通信框架,它使用 EventLoopGroup 来处理 I/O 事件(学习更多请参考:深入探索Netty的事件驱动模型与实现原理)。不同的 EventLoopGroup 实现针对不同的操作系统和应用场景优化性能。本文详细介绍了 Netty 中的五种 EventLoopGroup 实现:NioEventLoopGroupEpollEventLoopGroupPollEventLoopGroupKQueueEventLoopGroupIoUringEventLoopGroup,并提供了详细的代码示例和注释。

1. NioEventLoopGroup

NioEventLoopGroup 是基于 Java NIO 的 EventLoopGroup 实现,适用于多平台环境。它通过 Java NIO 的 Selector 来实现非阻塞 I/O 操作。

原理解释
  • NIO: Java NIO 提供了异步 I/O 操作,通过 Selector 来实现非阻塞 I/O。Selector 允许一个线程监视多个通道的 I/O 事件,如连接、读取、写入。Selector 减少了线程切换的开销。

  • Selector: Selector 是 Java NIO 的核心组件之一。它允许一个线程监视多个 Channel,通过注册 Channel 和感兴趣的事件(如 OP_READ、OP_WRITE),Selector 能够在事件发生时进行处理。

  • 事件循环: NioEventLoopGroup 使用 Selector 处理 I/O 事件。每个 NioEventLoop 线程负责管理和处理一组 Channel 的 I/O 事件。

示例代码注解
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class NioNettyServer {public static void main(String[] args) throws Exception {// 创建 NioEventLoopGroup 实例// bossGroup 负责接受客户端连接请求NioEventLoopGroup bossGroup = new NioEventLoopGroup(1); // 单线程用于接收连接请求// workerGroup 负责处理 I/O 操作NioEventLoopGroup workerGroup = new NioEventLoopGroup(); // 默认线程数,处理 I/O 事件try {// 创建 ServerBootstrap 实例ServerBootstrap bootstrap = new ServerBootstrap();// 配置服务器启动设置bootstrap.group(bossGroup, workerGroup) // 设置 bossGroup 和 workerGroup.channel(NioServerSocketChannel.class) // 使用 NioServerSocketChannel,适用于 NIO.childHandler(new ChannelInitializer<SocketChannel>() { // 设置 ChannelInitializer@Overrideprotected void initChannel(SocketChannel ch) {// 配置 ChannelPipeline,处理数据的流水线ChannelPipeline pipeline = ch.pipeline();// 添加 StringDecoder 以将 ByteBuf 解码为 Stringpipeline.addLast(new StringDecoder());// 添加 StringEncoder 以将 String 编码为 ByteBufpipeline.addLast(new StringEncoder());// 添加自定义的业务逻辑处理器pipeline.addLast(new ServerHandler());}});// 绑定端口并启动服务器ChannelFuture future = bootstrap.bind(8080).sync(); // 绑定端口 8080 并等待绑定完成// 等待服务器关闭future.channel().closeFuture().sync(); // 等待服务器通道关闭} finally {// 优雅地关闭线程组bossGroup.shutdownGracefully(); // 关闭 bossGroupworkerGroup.shutdownGracefully(); // 关闭 workerGroup}}
}

2. EpollEventLoopGroup

EpollEventLoopGroup 是基于 Linux 平台的 epoll 实现,专为高并发场景优化。

原理解释
  • epoll: epoll 是 Linux 提供的高效 I/O 多路复用机制,通过事件驱动的方式来处理大量并发连接。epoll 维护一个内核事件表来管理待处理的事件,减少了系统调用的开销。

  • 事件循环: EpollEventLoopGroup 使用 epoll 的 epoll_wait 系统调用来等待和处理 I/O 事件。它在 Linux 系统上提供了高性能的 I/O 处理能力。

示例代码注解
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class EpollNettyServer {public static void main(String[] args) throws Exception {// 创建 EpollEventLoopGroup 实例// bossGroup 负责接受客户端连接请求EpollEventLoopGroup bossGroup = new EpollEventLoopGroup(1); // 单线程用于接收连接请求// workerGroup 负责处理 I/O 操作EpollEventLoopGroup workerGroup = new EpollEventLoopGroup(); // 默认线程数,处理 I/O 事件try {// 创建 ServerBootstrap 实例ServerBootstrap bootstrap = new ServerBootstrap();// 配置服务器启动设置bootstrap.group(bossGroup, workerGroup) // 设置 bossGroup 和 workerGroup.channel(EpollServerSocketChannel.class) // 使用 EpollServerSocketChannel 实现.childHandler(new ChannelInitializer<SocketChannel>() { // 设置 ChannelInitializer@Overrideprotected void initChannel(SocketChannel ch) {// 配置 ChannelPipeline,处理数据的流水线ChannelPipeline pipeline = ch.pipeline();// 添加 StringDecoder 以将 ByteBuf 解码为 Stringpipeline.addLast(new StringDecoder());// 添加 StringEncoder 以将 String 编码为 ByteBufpipeline.addLast(new StringEncoder());// 添加自定义的业务逻辑处理器pipeline.addLast(new ServerHandler());}});// 绑定端口并启动服务器ChannelFuture future = bootstrap.bind(8080).sync(); // 绑定端口 8080 并等待绑定完成// 等待服务器关闭future.channel().closeFuture().sync(); // 等待服务器通道关闭} finally {// 优雅地关闭线程组bossGroup.shutdownGracefully(); // 关闭 bossGroupworkerGroup.shutdownGracefully(); // 关闭 workerGroup}}
}

3. PollEventLoopGroup

PollEventLoopGroup 是基于传统阻塞 I/O 实现的 EventLoopGroup,适合需要兼容旧系统的场景。

原理解释
  • poll: poll 是 Linux 和 Unix 系统提供的 I/O 多路复用机制,相比 select,poll 可以处理更多的文件描述符。它通过 pollfd 数组来检测多个文件描述符的状态。

  • 事件循环: PollEventLoopGroup 使用 poll 来处理 I/O 事件。与 epoll 和 NIO 相比,poll 在处理大量并发连接时性能较差,因为每次都需要遍历整个 pollfd 数组。

示例代码注解
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.oio.OioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class PollNettyServer {public static void main(String[] args) throws Exception {// 创建 OioEventLoopGroup 实例// bossGroup 负责接受客户端连接请求OioEventLoopGroup bossGroup = new OioEventLoopGroup(1); // 单线程用于接收连接请求// workerGroup 负责处理 I/O 操作OioEventLoopGroup workerGroup = new OioEventLoopGroup(); // 默认线程数,处理 I/O 事件try {// 创建 ServerBootstrap 实例ServerBootstrap bootstrap = new ServerBootstrap();// 配置服务器启动设置bootstrap.group(bossGroup, workerGroup) // 设置 bossGroup 和 workerGroup.channel(OioServerSocketChannel.class) // 使用 OioServerSocketChannel 实现.childHandler(new ChannelInitializer<SocketChannel>() { // 设置 ChannelInitializer@Overrideprotected void initChannel(SocketChannel ch) {// 配置 ChannelPipeline,处理数据的流水线ChannelPipeline pipeline = ch.pipeline();// 添加 StringDecoder 以将 ByteBuf 解码为 Stringpipeline.addLast(new StringDecoder());// 添加 StringEncoder 以将 String 编码为 ByteBufpipeline.addLast(new StringEncoder());// 添加自定义的业务逻辑处理器pipeline.addLast(new ServerHandler());}});// 绑定端口并启动服务器ChannelFuture future = bootstrap.bind(8080).sync(); // 绑定端口 8080 并等待绑定完成// 等待服务器关闭future.channel().closeFuture().sync(); // 等待服务器通道关闭} finally {// 优雅地关闭线程组bossGroup.shutdownGracefully(); // 关闭 bossGroupworkerGroup.shutdownGracefully(); // 关闭 workerGroup}}
}

4. KQueueEventLoopGroup

KQueueEventLoopGroup 是基于 macOS 和 BSD 系统的 kqueue 实现,提供高效的 I/O 操作。

原理解释
  • kqueue: kqueue 是 BSD 系统(包括 macOS)提供的高效 I/O 多路复用机制。它通过事件通知机制来处理 I/O 事件,与 epoll 类似。kqueue 提供了高效的事件通知,适用于 macOS 和 BSD 系统。

  • 事件循环: KQueueEventLoopGroup 使用 kqueue 的 kevent 系统调用来等待和处理 I/O 事件。kqueue 提供了高效的事件通知机制,适用于高并发场景。

示例代码注解
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.kqueue.KQueueEventLoopGroup;
import io.netty.channel.kqueue.KQueueServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class KQueueNettyServer {public static void main(String[] args) throws Exception {// 创建 KQueueEventLoopGroup 实例// bossGroup 负责接受客户端连接请求KQueueEventLoopGroup bossGroup = new KQueueEventLoopGroup(1); // 单线程用于接收连接请求// workerGroup 负责处理 I/O 操作KQueueEventLoopGroup workerGroup = new KQueueEventLoopGroup(); // 默认线程数,处理 I/O 事件try {// 创建 ServerBootstrap 实例ServerBootstrap bootstrap = new ServerBootstrap();// 配置服务器启动设置bootstrap.group(bossGroup, workerGroup) // 设置 bossGroup 和 workerGroup.channel(KQueueServerSocketChannel.class) // 使用 KQueueServerSocketChannel 实现.childHandler(new ChannelInitializer<SocketChannel>() { // 设置 ChannelInitializer@Overrideprotected void initChannel(SocketChannel ch) {// 配置 ChannelPipeline,处理数据的流水线ChannelPipeline pipeline = ch.pipeline();// 添加 StringDecoder 以将 ByteBuf 解码为 Stringpipeline.addLast(new StringDecoder());// 添加 StringEncoder 以将 String 编码为 ByteBufpipeline.addLast(new StringEncoder());// 添加自定义的业务逻辑处理器pipeline.addLast(new ServerHandler());}});// 绑定端口并启动服务器ChannelFuture future = bootstrap.bind(8080).sync(); // 绑定端口 8080 并等待绑定完成// 等待服务器关闭future.channel().closeFuture().sync(); // 等待服务器通道关闭} finally {// 优雅地关闭线程组bossGroup.shutdownGracefully(); // 关闭 bossGroupworkerGroup.shutdownGracefully(); // 关闭 workerGroup}}
}

5. IoUringEventLoopGroup

IoUringEventLoopGroup 是基于 Linux 的 io_uring 实现,旨在提供更高效的异步 I/O 操作。

原理解释
  • io_uring: io_uring 是 Linux 内核 5.1 引入的一种高效的异步 I/O 提供机制。它通过环形缓冲区和内核与用户空间之间的高效通信来减少系统调用开销,提高 I/O 操作的效率。

  • 事件循环: IoUringEventLoopGroup 使用 io_uring 提供的接口来提交和完成 I/O 操作。它能够在高负载的场景下提供优异的性能,减少上下文切换和系统调用开销。

示例代码注解

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.io_uring.IoUringEventLoopGroup;
import io.netty.channel.io_uring.IoUringServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;public class IoUringNettyServer {public static void main(String[] args) throws Exception {// 创建 IoUringEventLoopGroup 实例IoUringEventLoopGroup bossGroup = new IoUringEventLoopGroup(1); // 单线程用于接收连接请求IoUringEventLoopGroup workerGroup = new IoUringEventLoopGroup(); // 默认线程数,处理 I/O 事件try {// 创建 ServerBootstrap 实例ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bossGroup, workerGroup).channel(IoUringServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ChannelPipeline pipeline = ch.pipeline();pipeline.addLast(new StringDecoder());pipeline.addLast(new StringEncoder());pipeline.addLast(new ServerHandler());}});// 绑定端口并启动服务器ChannelFuture future = bootstrap.bind(8080).sync();future.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}
}

性能比较

1. NioEventLoopGroup

适用平台: 跨平台(Windows、Linux、macOS 等)

优点:

  • 跨平台支持: 兼容多种操作系统,适用于大多数应用场景。
  • 内置于 Java NIO: 不需要额外的本地库,易于使用。
  • 良好的通用性: 提供了非阻塞 I/O 操作,适用于大多数网络应用。

缺点:

  • 性能不如专用机制: 在某些高并发场景下,性能可能不如 epoll 或 kqueue。
  • 资源开销: 对于高负载应用,可能需要更多的资源来处理 I/O 操作。

2. EpollEventLoopGroup

适用平台: Linux

优点:

  • 高性能: epoll 提供了高效的 I/O 多路复用,适合高并发场景。
  • 低延迟: 减少了系统调用的开销,提供了更低的 I/O 操作延迟。
  • 高吞吐量: 能够处理大量的并发连接和事件。

缺点:

  • Linux 专用: 仅适用于 Linux 平台,不支持其他操作系统。
  • 复杂性: 需要特定的内核支持,使用时需要关注系统的配置和限制。

3. PollEventLoopGroup

适用平台: 跨平台(但主要用于旧系统)

优点:

  • 兼容性强: 适用于较旧的系统和环境,提供了一定的向后兼容性。
  • 简单: 实现简单,易于理解和使用。

缺点:

  • 性能较差: 在高并发场景下,性能不如 epoll 和 kqueue,可能成为性能瓶颈。
  • 资源消耗: 对于大量的文件描述符,性能下降明显。

4. KQueueEventLoopGroup

适用平台: macOS 和 BSD 系统

优点:

  • 高性能: kqueue 提供了高效的 I/O 多路复用,适合高并发场景。
  • 低延迟: 减少了系统调用开销,提供了低延迟的 I/O 操作。
  • 专用优化: 适合 macOS 和 BSD 系统的特性。

缺点:

  • 平台限制: 仅适用于 macOS 和 BSD 系统,不支持其他操作系统。
  • 工具支持: 相较于其他机制,工具和文档支持可能较少。

5. IoUringEventLoopGroup

适用平台: Linux(内核 5.1 及以上)

优点:

  • 超高性能: io_uring 提供了极高的异步 I/O 性能,减少了系统调用开销。
  • 低延迟: 通过环形缓冲区和批量操作,显著降低了 I/O 操作的延迟。
  • 高吞吐量: 支持批量提交和处理 I/O 请求,适合高负载场景。

缺点:

  • 内核要求: 需要 Linux 内核 5.1 或更高版本,老旧系统不支持。
  • 学习曲线: API 较为复杂,开发者需要理解其操作方式。
  • 资源消耗: 在高负载情况下,可能会增加内存和 CPU 的使用。

选择合适的 EventLoopGroup 实现可以根据操作系统和应用场景优化网络应用的性能和可维护性。

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

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

相关文章

springboot项目加载外部配置文件

springboot项目一般使用application.yml配置文件&#xff0c;数据库信息写在里面&#xff0c;做部署时&#xff0c;各个项目可能密码要求不一样需要修改密码&#xff0c;每次修改密码都要打包就比较麻烦&#xff0c;可以增加个外部配置文件进行处理&#xff0c;具体如下&#x…

javascript 常见设计模式

什么是设计模式? 在软件开发中&#xff0c;设计模式是解决特定问题的经验总结和可复用的解决方案。设计模式可以提高代码的复用性、可维护性和可读性&#xff0c;是提高开发效率的重要手段。 单例模式 1.概念 单例模式 &#xff08;Singleton Pattern&#xff09;&#xf…

深入理解二分法

前言 二分法&#xff08;Binary Search&#xff09;是一种高效的查找算法&#xff0c;广泛应用于计算机科学和工程领域。它用于在有序数组中查找特定元素&#xff0c;其时间复杂度为 O(log n)&#xff0c;显著优于线性搜索的 O(n)。本文将深入介绍二分法的原理、实现及其应用场…

单片机语音识别控制蓝牙通信

基于单片机语音识别控制&蓝牙控制 1、Arduino单片机语音控制1.1 直连1.2 蓝牙无线连接1.3 部分核心程序1.4 实物演示 2、51单片机语音控制2.1 直连2.2 蓝牙无线连接2.3 部分核心程序2.4 实物演示 3、STM32单片机语音控制3.1 直连3.2 蓝牙无线连接3.3 部分核心程序3.4 实物演…

器件频频更换为哪桩

曾想象&#xff0c;在一家大型研发型企业里有如下案例&#xff1a; 硬件工程师设计电路选择了器件库中的某器件&#xff0c;在批量试产产品时&#xff0c;却发现没有库存&#xff0c;即时申请采购&#xff0c;却发现货期相当长&#xff0c;一时难以采购&#xff0c;甚至根本不…

填志愿选专业,文科男生如何选专业?

又到了高考分数出炉&#xff0c;无数学子收获喜悦的季节&#xff0c;在分数刚出炉时&#xff0c;很多学生表现的异常兴奋&#xff0c;于他们而言&#xff0c;这么多年的努力终于有了收获&#xff0c;自己该考虑选择什么专业了。而毫不夸张的说&#xff0c;很多人在拿到专业目录…

HarmonyOS开发探索:使用Snapshot Insight分析ArkTS内存问题

识别内存问题 当怀疑应用存在内存问题的时候&#xff0c;首先使用DevEco Profiler的Allocation Insight来度量内存在问题场景下的大小变化以及整体趋势&#xff0c;初步定界问题出现的位置&#xff08;Native Heap/ArkTS Heap/dev等&#xff09;。 在初步识别内存问题出现的位置…

CentOS中使用SSH远程登录

CentOS中使用SSH远程登录 准备工作SSH概述SSH服务的安装与启动建立SSH连接SSH配置文件修改SSH默认端口SSH文件传输 准备工作 两台安装CentOS系统的虚拟机 客户机&#xff08;192.168.239.128&#xff09; 服务器&#xff08;192.168.239.129&#xff09; SSH概述 Secure S…

Mustango——音乐领域知识生成模型探索

Mustango&#xff1a;利用领域知识的音乐生成模型 论文地址&#xff1a;https://arxiv.org/pdf/2311.08355.pdf 源码地址&#xff1a;https://github.com/amaai-lab/mustango 论文题为**“**利用音乐领域知识开发文本到音乐模型’Mustango’”。它利用音乐领域的知识从文本指…

K 近邻、K-NN 算法图文详解

1. 为什么学习KNN算法 KNN是监督学习分类算法&#xff0c;主要解决现实生活中分类问题。根据目标的不同将监督学习任务分为了分类学习及回归预测问题。 KNN&#xff08;K-Nearest Neihbor&#xff0c;KNN&#xff09;K近邻是机器学习算法中理论最简单&#xff0c;最好理解的算法…

钉钉开放AI生态战略的真正价值到底是什么?很多人都没看懂

来源&#xff1a; 首席数智官 hello 大家好&#xff0c;我们是数字化领军者都在看的首席数智官。 关注我&#xff0c;每天给你讲一个商业案例。 今天我们要给你讲的是&#xff1a;钉钉开放AI大模型生态的战略意义到底是什么&#xff1f; 「谁先赢得苹果&#xff0c;谁就赢得…

AI大模型日报#0701:Meta发布LLM Compiler、扒一扒Sora两带头人博士论文

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE-4.0-8K-latest&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅读&#xff01;《AI大模型日报》今日要点&#xf…

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数

09 - matlab m_map地学绘图工具基础函数 - 绘制区域填充、伪彩色、加载图像和绘制浮雕效果的有关函数 0. 引言1. 关于m_pcolor2. 关于m_image3. 关于m_shadedrelief4. 关于m_hatch5. 结语 0. 引言 本篇介绍下m_map中区域填充函数&#xff08;m_hatch&#xff09;、绘制伪彩色图…

数据库连接池满问题

概述 当数据库连接池满时&#xff0c;可能会导致新的数据库连接请求无法被处理&#xff0c;进而影响应用程序与数据库的交互。以下是针对数据库连接池满问题的详细分析和解决策略&#xff1a; 问题分析 连接泄漏&#xff1a;应用程序在使用完数据库连接后没有正确地关闭连接&…

2.2章节python的变量和常量

在Python中&#xff0c;变量和常量有一些基本的概念和用法&#xff0c;但需要注意的是&#xff0c;Python本身并没有内置的“常量”类型。然而&#xff0c;程序员通常会遵循一种约定&#xff0c;即使用全部大写的变量名来表示常量。 一、变量 在Python中&#xff0c;变量是一…

唯一ID:雪花算法介绍与 Go 语言实现

介绍 snowflake 雪花算法可以在不依赖数据库的情况下&#xff0c;生成全局唯一的ID。雪花算法生成的ID是一个64位的整数&#xff0c;它由以下4部分组成: 时间戳&#xff1a;占用41位&#xff0c;精确到毫秒级&#xff0c;用于记录时间戳&#xff0c;差值形式可以使用69年。数…

数据库设计规范详解

一、为什么需要数据库设计 1、我们在设计数据表的时候&#xff0c;要考虑很多问题。比如: (1) 用户都需要什么数据?需要在数据表中保存哪些数据? (2) 如何保证数据表中数据的 正确性&#xff0c;当插入、删除、更新的时候该进行怎样的 约束检査 ?. (3) 如何降低数据表的 数据…

每天一个数据分析题(三百八十五)- 回归模型

在回归模型中&#xff0c;下列哪一项在权衡欠拟合&#xff08;under-fitting&#xff09;和过拟合&#xff08;over-fitting&#xff09;中影响最大&#xff1f; A. 多项式阶数 B. 更新回归参数w时&#xff0c;使用的是协方差矩阵求逆还是梯度下降 C. 使用常数项 D. 以上都…

python导入未找到tensorrt,No module named ‘tensorrt‘

(2024.7.1) 这个错误可能比较少见&#xff0c;是因为本人先装了tensorrt 10.1&#xff08;能够正常运行&#xff09;&#xff0c;后面又装了nvidia-tensorrt 7&#xff0c;后面不想用7了就把7卸了用回10&#xff0c;结果即使同一版本的tensorrt和nvidia-tensorrt都装了&#x…

毫米波雷达深度学习技术-2.1~2.2深度度量学习和成对方法

2 深度度量学习 有几种雷达应用程序旨在对一组预定义的类别进行分类&#xff0c;例如不同的人类活动或手势。然而&#xff0c;在实际环境中&#xff0c;存在的类不仅仅是预定义的类&#xff0c;这就把问题变成了一个开放集的分类任务。开放集分类意味着网络应该能够检测输入是否…