西郊有密林,
助君出重围✨
PyTorch框架的显存碎片处理
CUDA 显存碎片问题:诊断与解决方案 1. 什么是显存碎片 深度学习训练过程中,PyTorch 通过 CUDA Caching Allocator 管理 GPU 显存。该 allocator 会向 CUDA driver 申请大块 segment,然后在内部按需切分为更小的 block 分配给各个 tensor。 显存碎片指的是:一个大 block 被中间插入的小 block 切分后,即使大 block 对应的 tensor 已释放,由于小 block 仍然存活,整个 segment 无法合并回收。这种碎片并非物理设备上真实的地址碎片,而是 Caching Allocator 层面的逻辑碎片。 典型场景: Step 1: allocator 申请一个大 segment [LLLLLLLLLLLLLLLLLL] Step 2: 大 tensor 释放,但小 tensor 卡在中间 [____ss____________] ↑ 小 block 存活,segment 无法合并 Step 3: 下一轮需要同样大小的连续空间 → 找不到 → OOM 当这种情况以固定周期重复发生时(例如每个训练 step),碎片会不断累积,最终导致 OOM——即使 nvidia-smi 显示仍有大量空闲显存。 2. 如何判断 OOM 是否由碎片引起 2.1 使用 PyTorch Memory Visualizer PyTorch 提供了官方的显存分析工具:https://docs.pytorch.org/memory_viz ...
源码解读PyTorch新特性DtensorFastPath
DTensor FastPath 技术分析 1. 概述 DTensor 的核心工作流是:拆包参数 → 推断输出分片策略 → 可能做 redistribute → 执行本地算子 → 包装结果。 在 PyTorch 2.9 及之前版本中,这条路径完全在 Python 中执行,入口是 __torch_dispatch__。dispatch 是存在开销的,往往被 __torch_dispatch__ 拦截后在 Python 侧的调库开销更大,甚至可能超过一些小算子的执行时间。 关键 PR:https://github.com/pytorch/pytorch/pull/167051 核心思想:将操作搬到 C++,在 python_arg_parser.cpp 的 dispatch_on_subclass 层面拦截 DTensor,绕过 __torch_dispatch__ 协议,直接进入 C++ 实现的 dispatchDTensorOp。 2. 核心机制 2.1 __torch_dispatch__ 变更至 C++ 2.1.1 旧版本 __torch_dispatch__ 拦截逻辑 在旧版中,DTensor 是一个标准的 Tensor subclass,算子分发走的是 PyTorch 的标准 __torch_dispatch__ 协议。先梳理一下 2.9 之前是怎么把 DTensor 全部通过 __torch_dispatch__ 处理的。 当 DTensor 被构造时(通过 _make_dtensor),C++ 会检测它定义了 __torch_dispatch__,于是在 tensor 的 DispatchKeySet 上设置 Python + PythonTLSSnapshot 两个 key: ...
PyTorch内存管理:Caching Allocator(二)一文读懂Block
前言 PyTorch内存管理:Caching Allocator 的第一部分是对PyTorch内存管理的基本情况的概括。这篇文章讲从代码入手,尝试理解PyTorch Caching Allocator 中最核心的数据结构:Block,以及它在实际内存分配中是如何被管理的。 Block 先通过代码看看它的定义: struct Block { c10::DeviceIndex device; // gpu cudaStream_t stream; // allocation stream stream_set stream_uses; // streams on which the block was used size_t size; // block size in bytes size_t requested_size; // memory originally requested BlockPool* pool{nullptr}; // owning memory pool void* ptr{nullptr}; // memory address bool allocated{false}; // in-use flag bool mapped{true}; // is the virtual address range this Block references // backed by physical pages. Always true when // expandable_segment_ is null. When false // This Block will be aligned to the segment size // of its expandable_segment_. Block* prev{nullptr}; // prev block if split from a larger allocation Block* next{nullptr}; // next block if split from a larger allocation int event_count{0}; // number of outstanding CUDA events int64_t gc_count_base{0}; // get_free_blocks_call_count when Block is inserted std::shared_ptr<GatheredContext> context_when_allocated; // only set for the first block in the segment (when prev == null) // this records the frame information when cudaMalloc was called // whereas context_when_allocated records the last time we handed this // memory out from our cache. std::shared_ptr<GatheredContext> context_when_segment_allocated; ExpandableSegment* expandable_segment_{nullptr}; device、size、ptr:这几个参数比较好理解,由于是内存管理,就一定需要涉及到分配的设备、分配的内存大小以及在设备上的地址; requested_size:分配时请求的实际大小; stream:代表分配时的stream,默认所有操作会在该流进行; stream_uses:使用多流时记录使用过的流; prev、next:说明Block本质是一个链表,这也是为什么可以很方便的在Block内部执行切分、重组操作; event_count:未完成的cuda_event计数; 还剩一些涉及到虚拟内存、可扩展段以及资源管理的描述,我们放到后文去深究。总之,这几个属性就已经决定了如何申请、释放一个block,以及存在异步冲突怎么解决。 ...
电子产品的长期主义
刚刚完成学生到职场的身份转变————本质上是收入来源从父母到自己的转变,我开始回过头来review自己的消费观。以及,什么样的产品,能叫具有长期主义的电子产品。 作为一个学生而言,除了钱什么都不缺,我有的是时间和精力还有热情去做自己想做的事情,就拿手机举例,我会买小米手机————以一个较低的价格获取更好的硬件,然后去尝试给它刷各种系统、尝试解除温控、尝试root+探索。总而言之,是用时间(你要付出时间精力去学习理解参数并选择)换取金钱。 聊聊我的电子产品:2018,伴随着入学季,老妈为我购买了一台戴尔G3笔记本,iPad是哥哥给我的高考超过600分的奖励,另外一个电子产品是高中时期的红米手机。当然,这么多年过去了,手机已经不知道换了多少部,戴尔G3虽然也没有更换,但它的稳定性太差了,在它身上也没少折腾,拆机、清灰、换风扇、加内存条,现在不到必须使用window的情况下,我一般也不会打开它。至于这台iPad,3000块,七年过去了,二手市场的均价仍然在500块。虽然是非全贴合屏幕+60hz,但他对我产生过一些影响。本科的时候用这台iPad和一只Apple Pencil写下了无数的课堂笔记,至今做笔记这个功能它仍然可以满足我,当然,除此之外,现在它的作用也只有作为连接蓝牙的音乐播放器和电纸书了。我潜意识里认为的这台iPad是性价比最高的产品,原因应该是 它曾经足够好用 它现在依旧能基本满足作为一台平板的功能 它足够稳定,我几乎不需要考虑维修和折腾,充好电,它就可靠 它为我的成长做出过一些贡献 我现在慢慢觉得,一个你经常会用到的东西,它必须足够稳定和优秀,才能降低你对自身时间和精力的浪费,本质上,是用金钱换取为数不多的时间和精力了。我最近很喜欢的电子产品是Airpods Pro3,也是我终于舍得狠下心尝试的一款产品。我读书的时候也买过降噪耳机,Vivo TWS 3,降噪的确还算强,但是当时没有做足功课,它的音质我只能用垃圾形容,但我还是使用了它相当长的一段时间。直到我购买了Airpods Pro3,第一次戴上它我的脑海里只有震惊,给不接触电子产品的女朋友体验后,她说你在路上的时候千万不要戴它,注意安全。现在,它已经成为我上班时必备的工具之一了,我总是在想,如果上学时狠狠心购买的是Airpods Pro2就好了。一千块,其实几乎不会改变我的生活,但体验往往是截然不同的。 现在,对于电子产品的选购,我的买点: 稳定,一个产品稳定与否,取决于开发团队的态度,也决定了这个产品的生命周期 短期足够好用,长期能提供它作为该类型产品的基本功能 价格并不代表价格,贬值率才代表价格
迷茫与长期主义
时常感到焦虑,焦虑的来源是迷茫,是对未来生活的不确定性。但是有一些事情可以贯穿时间,在更长的跨度范围内给予一个人在某方面甚至整体上的成长,这就是长期主义。 想一下在我的视角里可以被称之为长期主义的事情:读书,电影(我指的是已经经过时间考验的经典的作品),投资(观念、认知、知识广度),音乐(一件乐器),以及我现在在做的事情(复盘、总结、记录)。但这些事情往往很花时间,而且是完整的大块时间,而不是碎片化的垃圾时间。 于我而言,这两件反而是相互矛盾的事情,正是因为它足够长期,反而使我无法从中获得积极的反馈。我知道我需要做一些长期的事情,但是时间和精力被工作挤满后,想做的事情只能一拖再拖。 但是我又好奇,如果我真的做了这些事情,它一定切切实实地会给予我回报吗?或者从概率的角度出发,它大概率会给予我一个正向的回报吗?如果答案是yes,那为什么不放弃工作,而专心于这几件长期的事情?如果答案是no,那它们还是长期主义的事情吗?