第十三篇:直接内存与零拷贝——NIO性能优化的底层真相

news2026/3/24 11:54:31
前言恭喜你完成了GC系列的学习现在你已经掌握了JVM内存管理和垃圾回收的核心知识。但JVM的内存世界还有一个重要的组成部分我们还没有深入探讨——直接内存。为什么Netty性能那么高为什么NIO比传统IO快零拷贝到底是什么这些问题的答案都指向同一个核心直接内存。今天我们就来深入剖析直接内存的本质、零拷贝技术的原理以及它们背后的权衡艺术。读完本文你将能回答直接内存和堆内存有什么区别为什么堆内存不能实现零拷贝零拷贝技术的原理是什么直接内存是如何被回收的这是JVM系列的性能优化专题也是理解现代Java高性能编程的关键。一、直接内存的本质1.1 什么是直接内存直接内存是本地内存的一部分由JVM提供了一套APIjava.nio包下的ByteBuffer.allocateDirect()来操作。// 堆内存JVM管理受GC控制byte[]heapBuffernewbyte[1024*1024];// 1MB在堆中// 直接内存操作系统管理不受GC直接控制ByteBufferdirectBufferByteBuffer.allocateDirect(1024*1024);// 1MB在本地内存1.2 两种内存的对比对比项堆内存本地内存管理方JVMGC操作系统分配速度快只在堆内划一块慢系统调用地址是否可变会变GC复制算法固定回收方式GC自动回收需手动或依赖Cleaner适用场景绝大多数Java对象元空间、直接内存、线程栈1.3 JVM与系统的关系关键认知JVM就是一个运行在操作系统上的普通进程尽管它很特殊。操作系统内存布局 ┌─────────────────────────────────────────────────────────────────────┐ │ 物理内存 │ ├─────────────────────────────────────────────────────────────────────┤ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ JVM进程 │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ 堆内存GC管理 │ │ │ │ │ │ Eden、Survivor、Old │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ 本地内存OS管理 │ │ │ │ │ │ 元空间、直接内存、线程栈、JNI、Code Cache │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────┘ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ 其他进程 │ │ │ └─────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────┘堆、栈、方法区等都是这个进程向操作系统申请来的内存空间的逻辑划分。二、为什么需要直接内存2.1 传统IO的两次拷贝先看传统IOFileInputStreamfisnewFileInputStream(data.txt);byte[]buffernewbyte[1024];fis.read(buffer);// 这一行背后发生了什么传统IO的完整流程硬盘 → 内核空间缓冲区 → JVM堆内存 [第一次拷贝] [第二次拷贝]详细步骤用户态 → 内核态切换JVM调用操作系统的read()接口DMA拷贝第一次硬盘 → 内核空间缓冲区DMADirect Memory Access是硬件技术不占用CPUCPU拷贝第二次内核缓冲区 → JVM堆内存CPU参与把数据从内核空间复制到用户空间传统IO流程图 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 硬盘 内核空间 用户空间 │ │ │ │ ┌─────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ DMA拷贝 │ 内核缓冲区 │ CPU拷贝 │ JVM堆内存 │ │ │ │ 数 │ ──────────→ │ │ ──────→ │ │ │ │ │ 据 │ │ │ │ byte[] │ │ │ └─────┘ └─────────────┘ └─────────────┘ │ │ │ │ ① ② │ │ (不占用CPU) (占用CPU) │ │ │ └─────────────────────────────────────────────────────────────────────┘为什么要有第二次拷贝用户程序不能直接访问内核空间安全性必须把数据从内核“搬”到用户空间程序才能用2.2 直接内存如何实现零拷贝ByteBufferdirectBufferByteBuffer.allocateDirect(1024);FileChannelchannelnewFileInputStream(data.txt).getChannel();channel.read(directBuffer);// 零拷贝直接内存的流程硬盘 → 直接内存用户空间 [唯一一次拷贝]直接内存流程图 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 硬盘 内核空间 用户空间 │ │ │ │ ┌─────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ │ DMA拷贝 │ 内核缓冲区 │ │ 直接内存 │ │ │ │ 数 │ ──────────→ │ │ ──X──→ │ │ │ │ │ 据 │ │ │ │ ByteBuffer │ │ │ └─────┘ └─────────────┘ └─────────────┘ │ │ └───────────────────┬───────────────────┘ │ │ │ │ │ 内核可以直接访问用户空间 │ │ 不需要第二次CPU拷贝 │ │ │ └─────────────────────────────────────────────────────────────────────┘关键直接内存是用户空间的内存但通过特殊机制内核可以直接访问它。这样既安全用户程序不能访问内核又避免了数据复制。2.3 核心疑问为什么堆不行但直接内存行“直接内存也是用户空间的堆也是为什么放到堆中不行但是直接内存可以”答案在于内存地址的固定性。堆内存为什么不行byte[]heapBuffernewbyte[1024];// Minor GC时如果heapBuffer存活它可能被复制到Survivor区// 地址变了内核要是正在往里写数据就完蛋了// 所以内核坚决不肯直接将数据写入堆中直接内存为什么行ByteBufferdirectBufferByteBuffer.allocateDirect(1024);// 这块内存不受GC影响地址永远不变// 内核可以放心地直接写入这就是那个“特殊机制”直接内存是固定的、不被移动的用户空间内存。三、零拷贝技术的演进3.1 传统IO的多次拷贝传统IO从硬盘读取数据并发送到网络需要经历多次拷贝传统IO硬盘 → 应用程序 → 网卡 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 硬盘 ──DMA──→ 内核缓冲区 ──CPU──→ 应用程序缓冲区 ──CPU──→ Socket缓冲区 ──DMA──→ 网卡 │ │ │ │ ① DMA拷贝 ② CPU拷贝 ③ CPU拷贝 ④ DMA拷贝 │ │ │ │ 总共4次拷贝2次CPU拷贝 │ │ │ └─────────────────────────────────────────────────────────────────────┘3.2 sendfile零拷贝Linux 2.1引入了sendfile系统调用实现了内核空间内的零拷贝// sendfile零拷贝FileChannelchannelFileChannel.open(Paths.get(data.txt));SocketChannelsocketSocketChannel.open();channel.transferTo(0,channel.size(),socket);// sendfile系统调用sendfile零拷贝 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 硬盘 ──DMA──→ 内核缓冲区 ──CPU──→ Socket缓冲区 ──DMA──→ 网卡 │ │ │ │ ① DMA拷贝 ② CPU拷贝 ③ DMA拷贝 │ │ │ │ 总共3次拷贝1次CPU拷贝 │ │ 减少了应用程序缓冲区的拷贝 │ │ │ └─────────────────────────────────────────────────────────────────────┘3.3 scatter/gather零拷贝Linux 2.4引入了sendfile的scatter/gather功能实现了真正的零拷贝scatter/gather零拷贝 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 硬盘 ──DMA──→ 内核缓冲区 ──DMA──→ 网卡 │ │ │ │ ① DMA拷贝 ② DMA拷贝 │ │ │ │ 总共2次拷贝0次CPU拷贝 │ │ │ │ 原理内核缓冲区中的描述符直接传递到网卡 │ │ CPU完全不参与数据拷贝 │ │ │ └─────────────────────────────────────────────────────────────────────┘3.4 mmap内存映射mmap将文件直接映射到内存应用程序可以直接访问// mmap内存映射FileChannelchannelFileChannel.open(Paths.get(data.txt));MappedByteBufferbufferchannel.map(FileChannel.MapMode.READ_ONLY,0,channel.size());// 现在可以直接访问buffer修改会直接写回文件mmap内存映射 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 硬盘 ──DMA──→ 内核缓冲区 ←─── 应用程序直接访问 │ │ ↑ │ │ │ 内存映射 │ │ │ │ │ ┌─────┴─────┐ │ │ │ 直接内存 │ │ │ └───────────┘ │ │ │ │ 优点应用程序可以直接操作内核缓冲区 │ │ 缺点文件修改会立即写回可能导致数据不一致 │ │ │ └─────────────────────────────────────────────────────────────────────┘四、直接内存的源码实现4.1 DirectByteBuffer的创建// DirectByteBuffer源码简化publicclassDirectByteBufferextendsMappedByteBuffer{DirectByteBuffer(intcap){super(-1,0,cap,cap);// 1. 分配直接内存baseunsafe.allocateMemory(size);// 2. 设置内存地址addressbase;// 3. 创建Cleaner虚引用cleanerCleaner.create(this,newDeallocator(base,size,cap));}// 分配内存的底层实现longallocateMemory(longsize){// 调用系统调用分配内存returnunsafe.allocateMemory(size);}}4.2 Cleaner的实现// Cleaner源码简化publicclassCleanerextendsPhantomReferenceObject{privatefinalRunnablethunk;privateCleaner(Objectreferent,Runnablethunk){super(referent,dummyQueue);this.thunkthunk;}publicstaticCleanercreate(Objectob,Runnablethunk){returnnewCleaner(ob,thunk);}publicvoidclean(){if(remove(this)){try{thunk.run();// 释放直接内存}catch(Throwablex){}}}}4.3 Deallocator的实现// Deallocator源码简化privatestaticclassDeallocatorimplementsRunnable{privatelongaddress;privatelongsize;Deallocator(longaddress,longsize){this.addressaddress;this.sizesize;}publicvoidrun(){if(address0){return;}// 释放直接内存unsafe.freeMemory(address);address0;}}4.4 直接内存的回收流程直接内存回收流程 ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 1. 创建DirectByteBuffer │ │ ├─ 分配直接内存本地内存 │ │ └─ 创建Cleaner虚引用关联DirectByteBuffer │ │ │ │ 2. DirectByteBuffer对象存活 │ │ └─ 直接内存被使用 │ │ │ │ 3. DirectByteBuffer对象不再被引用 │ │ └─ 成为垃圾堆中 │ │ │ │ 4. GC回收DirectByteBuffer对象 │ │ ├─ 虚引用Cleaner被放入ReferenceQueue │ │ └─ Cleaner线程处理队列调用clean() │ │ │ │ 5. clean()执行 │ │ └─ 调用unsafe.freeMemory()释放直接内存 │ │ │ └─────────────────────────────────────────────────────────────────────┘五、直接内存的权衡5.1 直接内存的优缺点✅ 优点零拷贝减少一次内存拷贝提升IO性能地址固定不受GC影响内核可以直接访问大内存友好不占用堆内存避免GC压力❌ 缺点分配慢每次分配需要系统调用回收复杂依赖Cleaner可能延迟回收内存泄漏风险忘记释放会导致物理内存耗尽上限不明确默认等于堆内存大小容易OOM5.2 什么时候用直接内存// 场景A小对象频繁分配不适合直接内存for(inti0;i1000000;i){// 每次都要系统调用性能极差ByteBufferdirectBufferByteBuffer.allocateDirect(64);}// 场景B大文件传输适合直接内存ByteBufferdirectBufferByteBuffer.allocateDirect(100*1024*1024);channel.read(directBuffer);// 一次拷贝性能极佳// 场景C网络IONetty场景// Netty默认使用直接内存因为网络IO频繁且数据量大5.3 直接内存的调优# 设置直接内存大小默认等于堆内存大小-XX:MaxDirectMemorySize512m# 查看直接内存使用情况jdk.nio.BufferPool.direct.capacity jdk.nio.BufferPool.direct.used jdk.nio.BufferPool.direct.count# 禁用显式GC可能影响直接内存回收-XX:DisableExplicitGC# 慎用可能阻止Cleaner工作六、一个帮你通透的类比快递柜模型传统IO两次拷贝你JVM想收快递读硬盘 ↓ 快递员内核把快递放到快递柜内核缓冲区 ↓ 你从快递柜取出快递搬到自己家堆内存 ↓ 现在快递在家了可以用了问题多了一次“从柜子搬回家”的动作。直接内存你提前买了一个特殊的快递柜直接内存这个柜子就在你家院子里用户空间 但快递员内核有钥匙可以直接把快递放进去 ↓ 你直接去院子里拿不用再从柜子搬回家为什么堆不行因为你的家堆会移动GC时搬家快递员不敢把快递直接放进去。七、Netty中的直接内存Netty是直接内存的典型应用场景。7.1 Netty的ByteBuf// Netty中的直接内存分配ByteBufdirectBufferUnpooled.directBuffer(1024);ByteBufdirectBufferPooledByteBufAllocator.DEFAULT.directBuffer(1024);// 对比堆内存ByteBufheapBufferUnpooled.buffer(1024);ByteBufheapBufferPooledByteBufAllocator.DEFAULT.heapBuffer(1024);7.2 Netty的内存池Netty实现了内存池来缓解直接内存分配慢的问题// Netty内存池源码简化publicclassPooledByteBufAllocator{privatefinalPoolArena[]directArenas;// 直接内存池privatefinalPoolArena[]heapArenas;// 堆内存池publicByteBufdirectBuffer(intcapacity){// 从内存池中获取避免频繁分配returndirectArena.allocate(capacity);}}7.3 Netty的零拷贝// Netty的零拷贝文件传输publicvoidsendFile(FileChannelfile,SocketChannelsocket){// 使用FileRegion实现零拷贝FileRegionregionnewDefaultFileRegion(file,0,file.size());socket.write(region);// 底层调用transferTo}八、常见面试题Q1直接内存和堆内存的区别是什么答管理方式堆内存由JVM管理受GC控制直接内存由操作系统管理不受GC直接控制地址可变性堆内存地址会因GC移动而改变直接内存地址固定分配速度堆内存分配快直接内存分配慢系统调用访问速度堆内存需要两次拷贝直接内存可以实现零拷贝Q2为什么堆内存不能实现零拷贝答因为堆内存中的对象可能被GC移动复制算法地址会变化。如果内核正在向堆内存写入数据时发生GC对象被移动会导致数据写入错误地址。直接内存地址固定不存在这个问题。Q3直接内存是如何被回收的答直接内存通过DirectByteBuffer对象关联的Cleaner虚引用回收。当DirectByteBuffer对象被GC回收时Cleaner被放入引用队列Cleaner线程处理队列调用unsafe.freeMemory()释放直接内存。Q4直接内存的默认大小是多少答默认等于堆内存大小-Xmx。如果堆内存是2GB直接内存默认也是2GB。可以通过-XX:MaxDirectMemorySize单独设置。Q5Netty为什么使用直接内存答Netty主要处理网络IO使用直接内存有以下优势零拷贝数据从内核直接写入直接内存减少拷贝减少GC压力直接内存不占用堆内存减少GC频率内存池Netty实现了内存池缓解直接内存分配慢的问题九、总结9.1 核心要点概念一句话解释直接内存用户空间的固定内存内核可以直接访问实现零拷贝零拷贝减少数据在内核空间和用户空间之间的拷贝次数传统IO硬盘 → 内核缓冲区 → 堆内存2次拷贝1次CPU拷贝sendfile硬盘 → 内核缓冲区 → 网卡2次拷贝0次CPU拷贝mmap文件直接映射到内存应用程序直接访问内核缓冲区9.2 直接内存的权衡┌─────────────────────────────────────────────────────────────────────┐ │ 直接内存的权衡 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ 优点 │ │ ├─ 零拷贝减少CPU拷贝提升IO性能 │ │ ├─ 地址固定不受GC影响 │ │ └─ 减少GC压力不占用堆内存 │ │ │ │ 缺点 │ │ ├─ 分配慢每次需要系统调用 │ │ ├─ 回收复杂依赖Cleaner可能延迟 │ │ ├─ 内存泄漏风险需要显式管理 │ │ └─ 上限不明确默认等于堆大小容易OOM │ │ │ └─────────────────────────────────────────────────────────────────────┘9.3 面试金句如果面试官问你“直接内存和零拷贝”你可以这样回答“直接内存是用户空间的固定内存不受GC影响内核可以直接访问。传统IO需要两次拷贝硬盘到内核缓冲区DMA内核缓冲区到堆内存CPU。直接内存可以实现零拷贝因为内核可以直接将数据写入用户空间的直接内存省去了一次CPU拷贝。直接内存通过DirectByteBuffer分配关联一个Cleaner虚引用当DirectByteBuffer被GC回收时Cleaner会释放直接内存。Netty使用直接内存和内存池结合sendfile系统调用实现了高性能的零拷贝网络传输。但直接内存分配慢、回收复杂需要权衡使用。”下篇预告掌握了直接内存和零拷贝你已经理解了Java高性能编程的核心技术之一。接下来我们将把这些知识应用到实战中——JVM参数调优与OOM排查。下一篇《JVM参数调优实战——从GC日志到参数调整》将带你学习如何通过分析GC日志找到性能瓶颈并进行针对性的参数调优。如果你觉得本文有帮助欢迎点赞、评论、转发

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…