PyTorch CUDA内存管理优化:深度理解GPU资源分配与缓存机制
在深度学习工程实践中,当训练大型模型或处理大规模数据集时,上述错误信息对许多开发者而言已不陌生。这是众所周知的
CUDA out of memory
错误——当GPU尝试为张量分配空间而内存不足时发生。这种情况尤为令人沮丧,特别是在已投入大量时间优化模型和代码后遭遇此类问题。
torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 512.00 MiB. GPU 0 has a total capacity of 79.32 GiB of which 401.56 MiB is free.
本文将深入剖析PyTorch如何优化GPU内存使用,以及如何通过定制其内部系统机制来充分发挥GPU集群的性能潜力。
GPU内存管理的关键性
在当代深度学习领域,随着数据集规模呈指数级增长及模型复杂度不断提升,高效利用GPU内存已成为技术实现的首要考量因素。无论GPU计算能力多么强大,板载内存容量始终是制约因素。每次内存分配与释放的影响往往比开发者预期更为深远。研究人员在训练大规模模型时常见的挑战主要包括:
内存容量限制是一个基本物理约束。如果训练过程或数据超出可用内存容量,训练将无法继续。计算效率方面,GPU理想状态应将主要时间用于矩阵运算,而非等待数据传输或协调多GPU工作。通信开销也是重要考量因素——GPU在通信期间实质上处于空闲状态,这是计算资源的浪费。为最小化此类开销,需合理利用节点间(相对较慢)和节点内(相对较快)通信带宽,理想情况下实现计算与通信的并行执行。
内存碎片化问题在频繁执行内存分配/释放操作(通过
cudaMalloc
和
cudaFree
)时尤为显著。这是一个核心挑战——即使总体空闲内存空间充足,碎片化也可能导致无法分配所需大小的连续内存块。与此同时,频繁的内存分配/释放不仅导致碎片化问题,还会引入大量计算延迟。此外,现代深度学习应用通常需要处理不同批量大小、动态网络架构或多种规格输入的模型,这要求内存管理系统能够在运行时高效适应变化,而不会造成显著性能损失。
以上因素共同凸显了PyTorch CUDA缓存分配器在整个内存管理体系中的核心地位。它通过系统性解决内存碎片和分配延迟问题,有效降低了内存操作的性能开销。
PyTorch CUDA缓存分配器的工作原理
为了直观理解PyTorch内存分配机制,我们可以观察使用PyTorch性能分析器在训练Llama 1B模型过程中的内存分配情况。
上图展示了使用PyTorch性能分析器记录的Llama 1B模型前4个训练步骤的内存配置文件
分析第2至第4步可以发现,它们的内存使用模式高度相似——首先在前向传播过程中激活值内存占用快速增加,随后在反向传播过程中进行梯度累积,同时随着反向传播的进行,用于计算梯度的激活值存储逐步释放。最后在优化器步骤中,系统需要访问所有梯度数据,完成优化器状态更新后,开始下一轮前向传播。
此处值得关注的问题是:为何第一步的内存使用模式与后续步骤存在明显差异?
这正是PyTorch CUDA缓存分配器发挥作用的体现。在第一步中,分配器初始化并预分配了内存块,为后续计算步骤提供加速,使之后的操作无需重复寻找空闲内存区域。第一步结束后,我们还可以观察到优化器状态的初始化,这通常会影响后续训练步骤的内存使用量分布。
从功能角度看,这个分配器实质上充当了PyTorch运行时与底层CUDA驱动程序之间的"智能中介",有效解决了前文所述的多项内存管理挑战。它通过最大化重用已释放的内存块来精细管理GPU内存的分配与回收,减少了系统调用开销,即使在高负载情况下也能保持稳定性能。与传统方式(每次创建张量时向系统请求新内存)不同,该分配器维护了一个预分配内存块的缓存池。当张量不再需要时,其占用的内存并不会立即返回给GPU系统,而是保存在这个内部池中以供后续重用。
从实际功能来看,这本质上是一个内存池化机制。因为重用缓存中的内存比每次创建张量时执行新的
cudaMalloc
调用效率更高,有效绕过了系统调用中常见的延迟问题。同时通过循环利用内存块,缓存分配器最小化了大型连续内存区域的争用情况,从而长期减少了内存碎片化。此外由于PyTorch的CPU执行通常先于GPU执行,缓存分配器通过其池化机制提前准备内存资源,有助于隐藏执行过程中可能出现的延迟,进一步优化整体性能。
CUDA缓存分配器的内存管理机制
该系统的内存管理可以分解为以下关键组件:
1、内存池化
在PyTorch框架中,当释放一个张量时,分配器并不会立即将该内存返回给GPU系统,而是将其捕获并存储在内部池中。这些缓存的内存资源可用于满足后续的分配请求,从而避免了重复调用
cudaMalloc
的系统开销。
2、重用与延迟释放
通过缓存内存块,PyTorch能够为内存需求与预分配块匹配的张量提供即时复用。"延迟释放"策略确保了内存资源的高效利用,避免了频繁的系统调用。只有当现有缓存块无法满足新的分配需求时,分配器才会向CUDA系统请求新的内存块。
3、碎片化优化
当可用内存被分割成多个小块,而这些小块无法满足较大的连续内存需求时,便产生了碎片化问题。缓存分配器通过主动合并内存块来应对这一挑战。它优先重用最近释放的内存并维护智能化缓存结构,减少碎片化的可能性,确保随时间推移能够保持更连续的内存空间。
4、平衡分配策略
分配器对大型和小型内存请求采用差异化处理策略。对于小批量训练等操作中频繁请求的细粒度内存块,系统会进行高效缓存。较大的内存块则采用不同的处理方式,以防止单一操作独占缓存空间,确保即时重用和整体可用性之间的平衡。
实际应用
PyTorch的内存分配器不仅在训练阶段,同样在推理过程中提供了显著的性能提升:
1、加速内存分配
通过最小化向CUDA发出新内存请求的频率,缓存分配器大幅降低了内存分配相关的系统开销,实现了训练循环中更快的迭代速度。
2、 资源使用优化
内存是训练大型神经网络时的关键资源约束。缓存机制实现了这一资源的更高效利用,通常使研究人员能够在内存限制较严格的GPU硬件上执行更复杂的实验。
3、碎片化控制
通过持续性地重用和循环利用内存块,系统有效控制了内存碎片化问题。这为动态内存操作提供了更一致的性能表现,即使在复杂的计算环境下也能保持稳定。
4、开发流程简化
由于分配器在后台自动运行,开发者无需手动跟踪和管理GPU内存状态。这使研究人员能够更专注于模型开发和算法优化,而非调试内存分配问题。
高级内存管理技术
除了缓存分配器的基础功能外,高级用户和专业开发者通常会采用以下策略进一步优化深度学习工作流中的内存利用:
1、 内存使用监控与可视化
在处理GPU内存问题时,精确了解内存使用状况至关重要。PyTorch提供了内置函数如
torch.cuda.memory_allocated()
和
torch.cuda.memory_reserved()
用于监控当前GPU内存状态。示例代码如下:
import torch print(f"Allocated Memory: {torch.cuda.memory_allocated() / (1024 ** 2):.2f} MB") print(f"Reserved Memory: {torch.cuda.memory_reserved() / (1024 ** 2):.2f} MB")
此外PyTorch还为开发者提供了内存快照生成和可视化工具,帮助深入分析模型运行机制和内存高峰消耗位置。
上图展示了训练过程中的内存快照
通过记录运行时分配与缓存内存状态,开发者可以准确定位哪些张量或操作消耗了过多内存。这些工具还提供了识别长时间训练会话中内存碎片问题的能力,同时有助于发现难以追踪的内存泄漏。内存快照分析在迭代研究和开发环境中尤为重要,因为在这些场景下,准确理解内存占用模式是有效扩展模型的关键因素。
若发现这些快照难以解读,可使用
_memory_viz.py
工具生成更直观的火焰图,如下所示:
上图显示了在PyTorch上训练ResNet时的内存分配火焰图
2、缓存主动管理
尽管缓存分配器设计为无需手动干预即可正常工作,但在特定场景下,显式清除缓存可能是必要的。这可通过调用
torch.cuda.empty_cache()
实现,该函数会释放缓存中的未使用内存。这一策略通常在不同模型或执行阶段转换时采用。然而,应谨慎使用此方法,因为释放缓存内存可能导致性能损失,特别是当后续操作需要立即重新分配大块内存时。
3、自定义CUDA内存分配器配置
环境变量如
PYTORCH_CUDA_ALLOC_CONF
允许开发者微调缓存分配器的行为。通过这一配置,可以设置最大缓存大小限制,并根据特定模型和训练范式调整分配策略。详细信息可参考PyTorch官方文档。
对于更高级用户,PyTorch支持集成自定义CUDA内存分配器。然而,这需要对CUDA和PyTorch内部机制有深入理解,通常用于针对特定应用场景的专门优化解决方案。
4、系统级性能分析
Nvidia的Nsight Systems
对于NVIDIA GPU用户,Nsight Systems和Nsight Compute等工具提供了GPU内存与计算任务处理的低层次分析能力。通过将性能分析数据与PyTorch内存统计关联,可以识别应用层面不易察觉的微观性能瓶颈。
5、动态分配策略研究
GPU内存管理的发展方向在于预测性内存使用模式分析和相应的资源预分配自适应策略。近期研究与社区实践正朝着整合考虑CPU和GPU内存的统一内存架构方向推进。关注这些技术进展可为开发者提供前沿内存优化方法的早期应用机会。
6、代码与训练优化实践
以下是几种不依赖高级技术而有效降低GPU内存使用的常见优化策略:
6.1 混合精度训练
混合精度训练技术利用16位与32位计算的组合,显著降低内存占用同时通常能保持模型精度。这种内存节约通常允许采用更大的批量大小或构建更复杂的模型结构。开发者可以通过Nvidia的Apex库或PyTorch内置的AMP功能相对简便地实现混合精度训练。
6.2 梯度检查点技术
梯度检查点策略实质上是用计算资源换取内存空间。通过在前向传播过程中仅保存选定层的激活值,并在反向传播过程中按需重新计算,可以显著降低模型的峰值内存占用。这种方法对于层数较多的深层网络尤为有效,因为在这些网络中内存使用与层数呈线性关系。
6.3 批量大小与模型架构调整
在频繁遇到内存限制时,通过实验逐步降低批量大小(同时采用梯度累积技术)来寻找性能与内存消耗的最佳平衡点是一种有效策略。同样,考虑对模型架构进行微调,在保持预测能力的同时最小化内存开销也是一种实用方法。
6.4 专业内存优化库应用
随着众多企业和研究机构投入深度学习/AI领域,各种社区开发的工具(如PyTorch Lightning)已经可供开发者使用。这些库通常集成了高效数据加载等最佳实践,并能简化长时间训练循环的管理复杂性。
6.5 原位操作技术
PyTorch支持在原位直接修改输入张量而不创建新张量的操作方式,这类操作通常由下划线后缀标识(如
add_()
、
relu_()
)。通过最小化中间张量分配,原位操作可以显著降低内存使用。
需要注意的是,虽然原位操作能提高内存效率,但它们可能干扰计算图结构并使梯度计算复杂化,因此在训练深度学习模型时应谨慎使用。然而,在模型推理阶段,由于不需要反向传播和梯度追踪,原位操作通常是非常有益的。此外,它们可以安全地应用于非叶节点张量或从计算图中分离的张量。尽管具有这些优势,原位操作应当选择性使用,以保持代码清晰度并避免意外副作用。
总结
高效GPU内存管理是构建可扩展、高性能深度学习系统的基础要素。虽然增加GPU数量是一种解决方案,但精通内存优化的开发者应着重于充分发挥现有硬件资源的潜力。深入理解PyTorch通过CUDA缓存分配器管理GPU内存的机制,能够为实现显著性能提升提供关键技术路径。
本文的核心观点在于:对于需要大规模部署生产模型的场景,主动监控和优化GPU内存使用至关重要。这可能涉及代码级优化、环境变量配置调整,在某些情况下甚至需要实现自定义内存分配器以实现最大计算效率。
https://avoid.overfit.cn/post/0dacd990b25343d690e3258ecdca8a28
作者:Sahib Dhanjal
相关文章:
PyTorch CUDA内存管理优化:深度理解GPU资源分配与缓存机制
在深度学习工程实践中,当训练大型模型或处理大规模数据集时,上述错误信息对许多开发者而言已不陌生。这是众所周知的 CUDA out of memory错误——当GPU尝试为张量分配空间而内存不足时发生。这种情况尤为令人沮丧,特别是在已投入大量时间优化…...
大模型基础知识扫盲
1 模型量化: 是什么:大模型量化是一种“压缩”技术,把模型里高精度的数字(比如32位浮点数)简化成低精度的数字(比如8位定点数)。 有什么用:它让模型占的空间更小,跑起来…...
《穿透表象,洞察分布式软总线“无形”之奥秘》
分布式系统已成为众多领域的关键支撑技术,而分布式软总线作为实现设备高效互联的核心技术,正逐渐走入大众视野。它常被描述为一条“无形”的总线,这一独特属性不仅是理解其技术内涵的关键,更是把握其在未来智能世界中重要作用的切…...
Python Cookbook-5.13 寻找子序列
任务 需要在某大序列中查找子序列。 解决方案 如果序列是字符串(普通的或者Unicode),Python 的字符串的 find 方法以及标准库的re模块是最好的工具。否则,应该使用Knuth-Morris-Pratt算法(KMP): def KnuthMorrisPratt(text,pattern): 在序列text中找…...
(自用)蓝桥杯准备(需要写的基础)
要写的文件 led_app lcd_app key_app adc_app usart_app scheduler LHF_SYS一、外设引脚配置 1. 按键引脚 按键引脚配置如下: B1:PB0B2:PB1B3:PB2B4:PA0 2. LCD引脚 LCD引脚配置如下: GPIO_Pin_9 /* …...
STM32Cubemx-H7-14-Bootloader(上)-ST和串口烧录
前言 本文主要研究,如果把ST单片机的SWDIO和SWDCLK引脚改成推挽输出后,我们又应该怎么重新烧录,以及如何使用串口下载。 当没有设置STlink烧录为引脚或者设置成其他功能的时候 如果想恢复,那么就在烧录之前,一直按住…...
“深入浅出:Java中的Lambda表达式及其应用“
前言 Lambda表达式是Java 8引入的一项强大特性,它允许以更加简洁的方式表示匿名函数。Lambda表达式不仅让代码更加简洁、清晰,而且为函数式编程提供了有力支持,从而提升了Java语言的表达能力。 在本文中,我们将深入浅出地探讨La…...
6.1es新特性解构赋值
解构赋值是 ES6(ECMAScript 2015)引入的语法,通过模式匹配从数组或对象中提取值并赋值给变量。: 功能实现 数组解构:按位置匹配值,如 let [a, b] [1, 2]。对象解构:按属性名匹配值,…...
【从0到1学RabbitMQ】RabbitMQ高级篇
学完基础篇之后我们对用户下单这个业务进行了改造,我们可以吧用户支付这个业务抽出来,放入队列当中去执行。如下图: 但是这里我们思考一下,如果MQ通知失败了,支付服务中支付流水显示支付成功,而交易服务中…...
200 smart pid
PID整定控制面板-S7-200 SMART 跟我学/跟我做之PID功能-系列课程-西门子1847工业学习平台官网 使用西门子200SMART进行PID调节 PID自整定 PID调节技巧_哔哩哔哩_bilibili S7-200 SMART PID PID常见问题...
AI制作PPT,如何轻松打造高效演示文稿
AI制作PPT,如何轻松打造高效演示文稿!随着信息化时代的到来,PPT已经成为了几乎所有职场人士、学生、讲师的必备工具。每个人都希望自己的PPT既有创意,又能高效展示信息。而在如今的科技背景下,AI的出现彻底改变了PPT的…...
如何用postman做接口自动化测试?
🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 本文适合已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求等基本操作。 工作环境与版本࿱…...
day29-贪心__134. 加油站__135. 分发糖果__860.柠檬水找零__406.根据身高重建队列
134. 加油站 这道题的贪心方法相当的巧妙。 首先,我们可以通过gas[i] - cost[i]得到第i个站点的净加油量(耗油量),那么如果我们现在考虑一个从某点a到某点b,那么如果a-》b范围之间的gas[i] - cost[i]存在负数,那么说明无法从a作…...
聊透多线程编程-线程基础-4.C# Thread 子线程执行完成后通知主线程执行特定动作
在多线程编程中,线程之间的同步和通信是一个常见的需求。例如,我们可能需要一个子线程完成某些任务后通知主线程,并由主线程执行特定的动作。本文将基于一个示例程序,详细讲解如何使用 AutoResetEvent 来实现这种场景。 示例代码…...
C# 组件的使用方法
类 Stopwatch 计算时间 Stopwatch sw new Stopwatch(); sw.Start(); // 要执行的代码块 Thread.Sleep(2000);sw.ElapsedMilliseconds // 消耗时间 Console.WriteLine(sw.ElapsedMilliseconds);组件 ListView 属性设置 外观 - View - Details 行为 - Columns -(…...
Python常用排序算法
1. 冒泡排序 冒泡排序是一种简单的排序算法,它重复地遍历要排序的列表,比较相邻的元素,如果他们的顺序错误就交换他们。 def bubble_sort(arr):# 遍历所有数组元素for i in range(len(arr)):# 最后i个元素是已经排序好的for j in range(0, …...
HTML5 服务器发送事件(Server-Sent Events)
1. 引言 HTML5 服务器发送事件(Server-Sent Events,SSE)是一种基于 HTTP 的服务器推送技术,允许服务器主动向客户端(如浏览器)发送实时更新。SSE 适用于单向通信场景,如新闻推送、实时价格更新…...
【C++游戏引擎开发】第12篇:GLSL语法与基础渲染——从管线结构到动态着色器
一、OpenGL渲染管线解密 1.1 OpenGL渲染管线流程图 #mermaid-svg-GrAgLUat95CVZKm0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GrAgLUat95CVZKm0 .error-icon{fill:#552222;}#mermaid-svg-GrAgLUat95CVZKm0 .e…...
阿里云负载均衡可以抗ddos吗
本文深度解析阿里云负载均衡的DDoS防护机制,通过实测数据验证其基础防御能力边界,揭示需结合云盾高防IP实现TB级流量清洗的工程实践。结合2023年Memcached反射攻击事件,提供混合云架构下的多层级防御方案设计指南。 云原生负载均衡的基础防护…...
动手学习:路径规划原理及常用算法
一、路径规划的基本原理 路径规划(Path Planning)是机器人导航的核心任务,目标是为机器人找到一条从起点到终点的无碰撞路径,同时满足约束条件(如最短路径、最优能耗、安全性等)。在人形机器人场景中&…...
Web前端性能指标Web3D性能优化
性能指标&评估方式 在Web3D性能优化之前,先了解性能指标&评估方式 前端性能指标评估与监测工具可分为以下几类,结合不同场景和需求,开发者可选择适合的工具进行性能优化: 一、浏览器内置工具 Chrome DevTools Performance 面板:记录运行时性能,分析CPU、内存使…...
Mujoco xml <option>
xml option option总起例子timestep(一般会用到)gravity(一般会用到)windmagneticdensityviscosityo_margino_solref, o_solimpo_frictionintegrator(一般会用到)cone(一般会用到)jacobian(一般会用到)solver(一般会用到)iterations(一般会用到)tolerance(一般会用到)noslip_it…...
如何用 nvm alias default 18.20.8 实现全局 Node.js 版本管理?一篇保姆级指南!!!
📝 如何用 nvm alias default 18.20.8 实现全局 Node.js 版本管理?一篇保姆级指南 🚀 1. 核心命令解析 🔍 nvm alias default 18.20.8 是 nvm 管理工具中用于设置全局默认 Node.js 版本的核心命令。它的作用是将指定版本锁定为所…...
推荐一款Nginx图形化管理工具: NginxWebUI
Nginx Web UI是一款专为Nginx设计的图形化管理工具,旨在简化Nginx的配置与管理过程,提高开发者和系统管理的工作效率。项目地址:https://github.com/cym1102/nginxWebUI 。 一、Nginx WebUI的主要特点 简化配置:通过图形化的界…...
Pytest多环境切换实战:测试框架配置的最佳实践!
你是否也遇到过这种情况:本地测试通过,一到测试环境就翻车?环境变量错乱、接口地址混乱、数据源配置丢失……这些「环境切换」问题简直像定时炸弹,随时引爆你的测试流程! 测试人员每天都跟不同的环境打交道࿰…...
大模型在网络安全领域的七大应用
1. 高级威胁检测与防御自动化 技术路径: 数据整合:聚合网络流量、终端日志、威胁情报等多源数据,构建多维特征库。行为建模:通过大模型的上下文理解能力,建立正常行为基线,识别偏离模式。动态策略生成&am…...
SpringBoot项目部署之启动脚本
一、启动脚本方案 1. 基础启动方式 1.1 直接运行JAR java -jar your-app.jar --spring.profiles.activeprod优点:简单直接,适合快速测试缺点:终端关闭即终止进程 1.2 后台运行 nohup java -jar your-app.jar > app.log 2>&1 &…...
【spark-submit】--提交任务
Spark-submit spark-submit 是 Apache Spark 提供的用于提交 Spark 应用程序到集群的命令行工具。 基本语法 spark-submit [options] <app-jar> [app-arguments]常用参数说明 应用程序配置 --class <class-name>: 指定应用程序的主类(对于 Java/Sc…...
机器学习中的回归与分类模型:线性回归、逻辑回归与多分类
在机器学习领域,回归和分类是两类重要的任务,它们各自有着不同的应用场景和模型构建方式。本文将详细介绍线性回归、逻辑回归以及多分类任务的相关内容,包括数据预处理、模型定义、损失函数的选择以及评估指标的计算。 一、线性回归…...
spark-rdd
Spark-core RDD转换算子 RDD 根据数据处理方式的不同将算子整体上分为 Value 类型、双 Value 类型和 Key-Value 类型。 Value类型: 1.map 将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换 mapPartitions map …...
Python 实现如何电商网站滚动翻页爬取
一、电商网站滚动翻页机制分析 电商网站如亚马逊和淘宝为了提升用户体验,通常采用滚动翻页加载数据的方式。当用户滚动页面到底部时,会触发新的数据加载,而不是一次性将所有数据展示在页面上。这种机制虽然对用户友好,但对爬虫来…...
pytorch TensorDataset与DataLoader类
读取数据 Dataset类 Dataset 是一个读取数据抽象类,所有自定义的数据集类需要继承该类。 该类主要实现以下三个功能 ①如何获取每一个数据及其label --> 抽象方法__getitem()__设置通过对象[索引]的方式获取每一个样本及其label ②告知一共有多少数据 -->…...
AI大模型与知识生态:重构认知的新时代引擎
📝个人主页🌹:慌ZHANG-CSDN博客 🌹🌹期待您的关注 🌹🌹 一、引言:我们如何获得知识,正在被AI彻底改写 从古代图书馆、百科全书,到搜索引擎、问答社区,人类获取知识的方式一直在进化。而随着 ChatGPT、DeepSeek、Grok 等 AI 大模型的到来,这一过程迎来了颠覆…...
Server-Sent Events一种允许服务器向客户端发送实时更新的 Web API
Server-Sent Events(SSE)是一种允许服务器向客户端发送实时更新的 Web API。它基于 HTTP 协议,提供了一种单向的、服务器到客户端的通信机制,客户端可以通过监听服务器发送的事件来接收实时数据。下面从原理、使用场景、代码示例等…...
电子电器架构 --- AI如何重构汽车产业
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁&am…...
操作系统CPU调度
简介 当CPU有大量任务要处理,但由于资源有限,无法同时处理。所有就需要某种规则来决定任务处理的顺序,这就是调度。 调度层次 根据调度频率与层次,共分为三种 高级调度 也称为作业调度(Long-Trem Scheduling),频次很低,它决定哪些进程从外存(硬盘)加载到内存中级调度 也…...
icoding题解排序
数组合并 假设有 n 个长度为 k 的已排好序(升序)的数组,请设计数据结构和算法,将这 n 个数组合并到一个数组,且各元素按升序排列。即实现函数: void merge_arrays(const int* arr, int n, int k, int* out…...
xHCI 上 USB 读写分析
系列文章目录 xHCI 简单分析 USB Root Hub 分析 USB Hub 检测设备 usb host 驱动之 urb xHCI那些事儿 PCIe MMIO、DMA、TLP PCIe配置空间与CPU访问机制 PCIe总线协议基础实战 文章目录 系列文章目录一、xHCI 初始化二、xHCI 驱动识别根集线器(RootHub)…...
SpringCloud Alibaba 之分布式全局事务 Seata 原理分析
1. 什么是 Seata?为什么需要它? 想象一下,你去银行转账: 操作1:从你的账户扣款 1000 元操作2:向对方账户增加 1000 元 如果 操作1 成功,但 操作2 失败了,你的钱就凭空消失了&…...
《C语言中的“魔法盒子”:自定义函数的奇妙之旅》
🚀个人主页:BabyZZの秘密日记 📖收入专栏:C语言 🌍文章目入 一、引言二、自定义函数的创建(一)基本结构(二)一个简单的例子 三、自定义函数的使用(一…...
【Spring】IoC 和 DI的关系、简单使用,从“硬编码“到“优雅解耦“:IoC与DI的Spring蜕变之旅
1.IoC 和 DI的关系 IoC(Inversion of Control,控制反转)和DI(Dependency Injection,依赖注入)是Spring框架中紧密相关但又有所区别的两个概念。理解它们的联系,可以帮助我们更深刻地掌握Spring…...
43、RESTful API 保姆教程
RESTful API 目录 RESTful API简介RESTful设计原则RESTful设计规范RESTful统一返回体JAX-RSJAX-RS与SpringBoot集成构建Restful服务实践总结一、RESTful API 简介 REST(Representational State Transfer)是一种基于HTTP的web服务架构风格,RESTful API则是遵循REST原则的网…...
ASP.NET Core 性能优化:客户端响应缓存
文章目录 前言一、什么是缓存二、客户端缓存核心机制:HTTP缓存头1)使用[ResponseCache]属性(推荐)2)预定义缓存配置(CacheProfile)3)手动设置HTTP头4)缓存验证机制&#…...
算法导论(递归回溯)——递归
算法思路(21) 递归函数的含义: 创建一个递归函数,该函数接受两个链表的头结点作为输入,返回合并后的链表的头结点。 选择较小的节点: 在函数体内,首先比较两个链表的头结点的值,选择…...
从接口400ms到20ms,记录一次JVM、MySQL、Redis的混合双打
1. 场景:促销活动的崩溃 接到报警短信,核心接口响应时间突破5秒,DB CPU飙到100%。 用Arthas抓取线上火焰图后发现: ---[ 4763ms ] com.example.service.OrderService.createOrder() |---[ 98% ] com.example.m…...
Excel通过VBA脚本去除重复数据行并保存
一、方法1:使用字典动态去重并保存 适用场景:需要灵活控制去重逻辑(如保留最后一次出现的重复项)时 Sub 动态去重保存到新表()Dim srcSheet As Worksheet, destSheet As WorksheetDim dict As Object, lastRow As Long, i As LongDim key A…...
Mysql表的操作(2)
1.去重 select distinct 列名 from 表名 2.查询时排序 select 列名 from 表名 order by 列名 asc/desc; 不影响数据库里面的数据 错误样例 : 但结果却有点出乎意料了~为什么会失败呢? 其实这是因为书写的形式不对,如果带了引号,…...
#Linux内存管理# 在ARM32系统中,页表是如何映射的?在ARM64系统中,页表又是如何映射的?
一、ARM32系统页表映射 1. 层级结构与地址划分 默认实现:采用两层映射(PGD→PTE),合并Linux标准三级模型中的PMD层。 虚拟地址解析(以4KB页为例): Bits[31:20]:一级页表(…...
prometheus整合jmx_exporter 使用jmx_exporter监控Kafka
docker-compose部署kafka集群;单节点单zk-CSDN博客 springboot整合kafka;docker部署kafka-CSDN博客 kafka使用SSL加密和认证--todo_ssl.truststore.location-CSDN博客 version: 3.8services:zookeeper1:image: zookeeper:3.9.1container_name: zook…...
深度学习实战:从零构建图像分类API(Flask/FastAPI版)
引言:AI时代的图像分类需求 在智能时代,图像分类技术已渗透到医疗影像分析、自动驾驶、工业质检等各个领域。作为开发者,掌握如何将深度学习模型封装为API服务,是实现技术落地的关键一步。本文将手把手教你使用Python生态中的Fla…...