分享丨内存带宽
匿名用户
427
2024.11.11
2024.11.11
发布于 贵州

内存带宽问题

内存带宽:指处理器可以从内存读取(load)数据或将数据存储(store)到内存的速率。单位通常是(MB/s)。
CPI代表每条指令会消耗CPU的周期数,如果该值越大,代表CPU经常陷入停滞,通常都是在访问内存(性能之巅p217)。如果经常访问内存,CPU会因为经常停滞等待I/O而导致高使用率,而不仅是在执行指令。
字长:32位或64位---指整数大小和寄存器宽度,表示地址空间大小和数据通路宽路。

抓取工具和现象
目前可以通过perf mem分析内存访问,能具体看到导致内存放大的函数,但perf mem仅能看到每个函数的单次访存记录,无法统计各函数访存代价的占比,通过文本处理的方式可以统计出各函数在所有访存代价中的占比。通过Intel开源的pcm-memory工具仅能查看各内存通道产生的带宽,无法具体到线程级别。通过PerTaskMemBWMonitoring工具可以查看某个进程或线程产生的内存带宽,但仅支持部分X86型号(如Xeon-SP)。pcm-memory工具和PerTaskMemBWMonitoring工具结合可以验证PerTaskMemBWMonitoring工具的正确性。

如上图所示,是在dpc计算节点上抓的内存带宽,经过计算,dpc对vdbench下的IO内存放大比达到近50倍。除了应用产生的合理的内存放大,其他不合理的内存放大是解决该问题的关键。通过perf mem抓取的内存带宽top函数如下:
加载(load)的top函数:

经查看,所抓取的这些函数也的确是需要经常操作内存的函数,说明抓取到的函数的确是导致内存放大的top函数。
存储(store)的top函数:

措施
由于CPU频繁的从内存加载(load)和存储(store),导致内存带宽放大。降低内存带宽的主要思路还是应该从降低程序中不必要的内存读写出发。
即降低下图中的load和store指令时延,使CPU尽量从较近的寄存器中存取数据。

优化思路:
 选择适当的算法和数据结构,防止伪共享等现象的出现。
 将内存带宽高的算法升级为SIMD,如Crc32,memcpy。
 消除不合理的内存访问。
 优化循环低效率(如将公共的部分抽离,频繁访问的变量声明为临时寄存器变量等,只将最后计算出的值一次存入内存)。
 寄存器溢出:合理评估寄存器变量的数量,防止寄存器溢出,还是会去内存加载变量。
访存函数调用关系图表明,函数设施内存管理相关的接口和diff(crc32)是造成内存放大的大头。
问题
目前的确抓取到了可能导致内存放大的函数,但仍然无法根据现有的值计算出每个函数具体导致了多大的内存放大,只能粗略评估。
抓取到的这些函数过于封装,不易识别以上情况的优化点,甚至没有。
抓取到的这些函数的确是需要频繁访问内存的函数,如何识别不合理的内存访问,还需要探索。

评论 (0)