内存优化系列文章(1)AI性能加速1.3x倍就靠一个环境变量!
虚拟内存、物理内存、内存分配、内存泄漏、TLB 不命中、缺页异常这些看似熟悉的计算名词却似懂非懂,没关系!本系列文章通过理论和实战带你一网打尽!
自从工作中接触到深度学习内存优化知识以来,白丁决定重新系统研究一下计算机背后的内存故事。通读本文你将获得以下干货知识:
为什么内存优化可以大幅度提升深度学习算法的性能?如何通过工具定量分析内存优化带来的性能好处?
操作系统为什么采用虚拟内存管理而不直接使用物理内存?虚拟内存的核心思想是什么?虚拟内存管理对应用程序的性能有什么影响?应用程序如何从操作系统申请和释放内存?
常见内存分配算法 PTMalloc、TCMalloc 和 Jemalloc 详解
什么是零拷贝?
进程中的内存管理和共享内存?
如何利用虚拟内存进行 I/O 优化?
BERT 模型内存优化
一个环境变量性能直接飙升1.3x, 内存优化这么牛?## 标题
在实际的优化工作中,我们经常利用 TCMalloc 或者 JEMalloc 来替换 glibc 中默认使用的 PTMalloc 来获得更好的模型性能。 以下图中BERT 模型在 Pytorch 中的推理为例, 在采用了TCMalloc之后,BERT 的吞吐量直接从60.8 sentence/s 飙升到79.2 sentence/s,性能直接提升了1.3x。
所谓知其然并知其所以然。替换 malloc 算法其实就是一个export 一个 LD_PRELOAD 环境变量的事(下一篇就给你教程),为什么会发生这么大的性能影响?这会影响操作系统里的哪些指标?如何通过现有的工具分析?
###缺页异常大幅度降低
简单来说,现代操作系统采用虚拟内存(后续详解)的管理机制,系统在访问某一内存页时需要首先利用页表机制将虚拟地址映射到物理地址,如果在查找的过程中发现页表中没有对应的映射条目,就会发成缺页异常。因为要执行完异常处理程序后,程序才能继续执行,这难免会拖累性能。在 Linux 系统中 ps 命令可以用来查看进程的缺页状况。在本实验中,我们统计在实际推理过程中(不包括模型初始化的过程)的 minflt 的情况如下图所示。相对而言,PTMalloc 的缺页次数明显多于两种 malloc 算法。这也在一定程度上解释了为什么推理的性能会有如此大的差距。对于内存机制而言,除了缺页可能导致程序变慢之外?还有什么可能影响程序性能呢?
ps -o majflt, minflt -C program
TLB 不命中率降低
上述分析中提到虚拟内存管理机制需要通过查询页表才能获取实际的物理地址。页表通常存储在物理内存中,类似于缓存机制,常用的页表项会被加载到 TLB (Translation Look-aside Buffer)中以加快页表的访问。内存映射单元(MMU)会优先访问 TLB 获取物理地址映射,但是如果 TLB 不命中将导致 MMU 需要从内存中加载页表项,因此 TLB 不命中势必会影响程序的执行效率。perf 是一个强大的性能分析工具,它可以观测到诸如缓存不命中、缺页异常、TLB 不命中等系统级的性能事件。下图的分析结果表明,相对于其他两种 malloc 算法,PTMalloc 也具有明显的 TLB 不命中比例,这也在一定程度上拖累了程序性能。试想,缺页异常表示的是页表项中没有该虚拟页到物理内存的访问。那也意味着这个虚拟地址很可能是第一次访问,在访问该虚拟地址之前没有建立映射关系,因此,缺页异常必然导致 TLB 不命中。
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses your_program
上文我们介绍了 malloc 算法对程序性能的影响以及背后的原因分析。下一篇文章我们将提供 TCMalloc 和 JeMalloc 快速入门指南以及使用时候的注意事项。更多内存优化的知识请持续关注 "程序员的大厂之路" 微信公众号
作者简介:小编是某知名企业的一名深度学习软件工程师,主要从事深度学习性能优化方面的工作包括但不限于深度学习框架优化、模型量化、分布式训练等。欢迎留言一起讨论计算机基础,深度学习性能优化等方面的知识。