惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

L
LINUX DO - 热门话题
Stack Overflow Blog
Stack Overflow Blog
B
Blog
WordPress大学
WordPress大学
Project Zero
Project Zero
P
Palo Alto Networks Blog
阮一峰的网络日志
阮一峰的网络日志
博客园 - 司徒正美
有赞技术团队
有赞技术团队
S
SegmentFault 最新的问题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
小众软件
小众软件
T
Tailwind CSS Blog
Forbes - Security
Forbes - Security
F
Full Disclosure
SecWiki News
SecWiki News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hacker News: Ask HN
Hacker News: Ask HN
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs
Cisco Talos Blog
Cisco Talos Blog
G
Google Developers Blog
J
Java Code Geeks
Google DeepMind News
Google DeepMind News
人人都是产品经理
人人都是产品经理
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Recorded Future
Recorded Future
O
OpenAI News
Spread Privacy
Spread Privacy
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
Cybersecurity and Infrastructure Security Agency CISA
S
Securelist
V
Vulnerabilities – Threatpost
Y
Y Combinator Blog
IT之家
IT之家
U
Unit 42
腾讯CDC
S
Security Affairs
C
Cisco Blogs
Schneier on Security
Schneier on Security
The Last Watchdog
The Last Watchdog
B
Blog RSS Feed
宝玉的分享
宝玉的分享
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
S
Security @ Cisco Blogs
Cyberwarzone
Cyberwarzone
T
The Blog of Author Tim Ferriss

CUDA

招聘|外资对冲基金|机器学习工程师 [英伟达] [北京或者上海] [深度学习性能优化-CUDA] - V2EX 训练 SVC 声音模型 2060 12g 和 8G 的 3060TI 哪个快 - V2EX win11 使用 cuda 调用两个 gpu 计算时,自带任务管理器看不到 gpu2 的使用率? - V2EX [cuda 函数劫持] cuda12.2 版本新增了一个函数 cuGetProcAddress_v2,请问如何进行劫持? - V2EX [英伟达 NVIDIA] [上海/北京/深圳] [CUDA 相关岗位] - V2EX 如果实现 openmpi 和 cuda 编程的结合 - V2EX 怎么把显卡显存中的 rgba 图像渲染输出? - V2EX 如何实现 CUDA 的分布式并行运算? - V2EX 游戏本上用 cuda 是什么体验? - V2EX Tesla k20m 使用问题 - V2EX CUDA on WSL - V2EX 关于使用 GPU 生成随机数(cuda/opencl) - V2EX cuda 计算 titan v 为何比 rtx2080ti 更慢? - V2EX DeOldify - V2EX 不死心问一下笔记本 1050 支持 cudnn 吗? - V2EX Python+CUDA,大家有什么推荐的值得深入学习了解的项目或者著作么? - V2EX 写 CUDA,使用专业卡与游戏卡有什么区别? - V2EX 急求推荐个 5k 人民币左右的运算 GPU,能装 ubuntu 就行,跑深度学习用的,必须在 nvidia 运算能力表里面的卡 - V2EX OpenCL/CUDA/云存储求牛人指导,小伙伴们来围观 :) - V2EX 想了想用 WebGL 能不能做科学计算 - V2EX 有人用雷电转 PCI-e 设备外接显卡跑过 CUDA 的么? - V2EX 关于 GPU CUDA 编程的优化问题 - V2EX CPU or GPU? CUDA or OpenCL ? - V2EX
Set Max_split_size_mb To Avoid Oom In Pytorch - V2EX
GopherDaily · 2023-07-26 · via CUDA

我们在 k8s 中部署了 stable-diffusion-webui 供任何想要体验的 Stable Diffusion Model 的用户使用. 随着一个又一个的请求, 我们频繁的遇到 CUDA 的 OOM 错误. 其中的一小部分确实是因为用户请求需要的资源超过了对应 GPU 能够提供的内存.

剩下的, 占大部分的, 是类似如下的令人困惑的场景.

{"error": "OutOfMemoryError", "detail": "", "body": "", "errors": "CUDA out of memory. Tried to allocate 1024.00 MiB (GPU 0; 11.76 GiB total capacity; 7.92 GiB already allocated; 784.31 MiB free; 10.63 GiB reserved in total by PyTorch) If reserved memory is >> allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF"}

根据对 memory_stats 的理解:

  • GPU 的内存是 11.76G
  • pytorch 已经从 GPU 出请求的内存是 10.63G
  • pytorch 已经分配给用户的内存是 7.92G
  • pytorch 还可以分配的内存为 784.31M, 远小于 reserved 减 allocated 的 2.71G

这部分内存去哪儿了呢? 为什么在用户申请的时候依然没有被回收呢?

当用户请求内存时, pytorch 的处理流程可以简化为:

  1. 尝试通过 get_free_block 去寻找满足要求的空闲 Block
  2. 如果失败, 则通过 trigger_free_memory_callbacks 去回收已分配但不再使用的 Block 后, 再次尝试 get_free_block
  3. 如果失败, 则通过 alloc_block 去向 GPU 申请新的 Block
  4. 如果失败, 则通过 release_available_cached_blocks 将已申请但未分配的 Block 释放后再次尝试 alloc_block
  5. 如果失败, 则通过 release_cached_blocks 将所有已申请但未分配的 Block 释放, 再次尝试 alloc_block

我们注意到 pytorch 向 GPU 申请和分配给用户的内存都以 Block 为单位. pytorch 向 GPU 申请的 Block 大小并不固定, 受当时用户请求内存大小的影响. 用户释放内存后, Block 返回给 pytorch 并成为空闲状态. 用户下次申请时优先会复用空闲 Block, 而不是直接向 GPU 申请.

如果用户申请的内存大小小于满足要求的空闲 Block, pytorch 会进行一次 split 操作. 将 Block 分割成两个 Block, 除去用户请求大小的内存会被分割成一个独立的 Block, 留待后用并通过双向链表和分配给用户的 Block 相关联.

trigger_free_memory_callbacks 的回收过程会将相邻的空闲 Block 合并, 提高后续分配的灵活性.

相较于其他内存管理机制, pytorch 的内存管理相对简略:

  • pytorch 回收 Block, 只尝试合并相邻的空闲的 Block, 并不会进行搬运操作来处理不相连的空闲 Block
  • 一旦 Block 被分割, 则 pytorch 无法将其释放. cudaMalloc 和 cudaFree 是对称的, 你无法仅释放某次分配的一部分内存.

上述的两点, 造成了 pytorch 可能因为 Block 碎片化, 导致大量内存无法被使用.

假设在某次分配内存时, pytorch 根据用户请求向 GPU 申请了一个 256M 的 Block.
<-------------------------- 256M ----------------------------->

经过多次分配和回收, 其使用情况可能变成如下.
<-- 28M(allocated) --><-- 100M(free) --><-- 28M(allocated) --><-- 100M(free) -->

此时如果用户申请 160M 内存:

  • 虽然空闲的总内存大于 160M, 但是因为没有大于 160M 的 Block, 所以无法分配
  • pytorch 也无法将空闲的 100M+100M 内存返回给 GPU, 导致也无法向 GPU 申请 160M 内存.

max_split_size_mb 的作用

max_split_size_mb 的作用在于禁止 pytorch 对任何大于该大小的 Block 进行分割操作, 从而控制碎片化的程度. 我们上文讲诉的都是在未主动设置 max_split_size_mb 的情况下的逻辑, 此时 max_split_size_mb 取默认值 MAX_INT.

我们并没有找到官方推荐的 max_split_size_mb, 我们也不熟悉 pytorch 和 nvida, 很难给出一个很好的推荐值. 从实际使用来和直观逻辑来说, 128/256/512 之类的值都是可选的, 切实的避免了 OOM, 也没有导致明显的性能负担.

garbage_collection_threshold

pytorch 默认仅在无法获取到合适的空闲 Block 时触发回收, 这个值可以控制当 allocated/capacity 超过此值时触发主动的回收.

Expandable Segments

pytorch 最新(>v2.0.1)的 master 分支中添加了 Expandable Segments, 可能也可以缓解碎片化的问题.

References