相信我们从事IT基础设施开发的朋友们都听说过NUMA,以前自己也零零散散地听到过一些概念,还仍感不太系统,最近研究的基于scylla的DB时,就发生过内存回收compaction的问题。今日在几篇文章和论文的推动下,打算用此文将NUMA讲得全面一点,但也不会太底层,所以主打核心概念/设计思想,稍展开细节(展开多了感觉自己都成翻译员了 ~~~)。


从处理器到内存间的电子信号速度决定了CPU访问内存的延迟,对于大规模硬件系统需要OS支持NUMA架构以便CPU访问最靠近它的内存。比起访问remote memory,local memory 访问不仅延迟低(100ns),而且也减少了对公共总线(interconnect)的竞争。因此合理地放置数据(比如直接调用NUMA api)对利用内存带宽增加吞吐有很好的作用。

一个典型的multisocket的系统是带有2个sockets,因此称之有2个numa nodes(solaris称为locality group)(linux可查看/sys/devices/system/node),从最靠近CPU的那个node上分配的内存称为node local。现在OS一般不需要应用直接调用NUMA api来合理放置数据,OS内部一般有启发式的方法来对用户透明地处理数据。不过对于noncache-coherent 系统,启发式算法将会更加有难度。

OS如何管理NUMA

  • 策略一
    视所有内存为同等role,没有性能之分
    这种方式也许在NUMA系统设计之初是可采用的,OS不需要什么特别的支持,性能好坏取决于应用如何分配数据
  • 策略二:memory stripping
    对于一个大小超过一个cache line的结构,其访问模式是在各个CPU上进行轮换,这样访问NUMA内存的整体代价可以平均;但此法仍不是最优的
  • 策略三:heuristic memory placement for applications
    OS支持NUMA,称为numa-aware os,BIOS和相关固件也要提供支持,可在运行时动态enable/disable。一般只有那些对性能要求非常高的kernel组件才会考虑更多的代码支持,要求不高的地方统一看待。

一般OS会假设应用在靠近CPU的node上分配内存,但有时并不能完全保证这一点,如果应用申请多于一个numa node的内存,或者有更多的CPU可以用,app被迁移。一般小的Unix*工具可以保证这一点,但对于大量使用内存和CPU的应用来讲,就需单独调优;linux上也有相关工具可以设置memmory affinity,如taskset, numactl (可以像tasket一样给进程分配CPU,还可分配numa node);
对于大的结构,如若要被各个线程所共享,放置时惟有交错访问以平分性能损失

Linux如何管理NUMA

linux以zones的方式管理内存,一个numa node可管理多个zone,可通过cat /proc/zoneinfo来查看memory distributions;

memory policy策略[2]

memory policy指的是在NUMA系统下的内存分配到哪个node上的问题。一种memory policy由一个mode, 可选的mode flags,和可选的nodes组成。分配针对的对象可以是整个系统,可以是某个进程,可以是进程的某段内存区域

  • 系统默认级别
    将使用local allocations
  • 任务/进程级别
    如果没有被设置,回退到默认;如果被设置,可由fork, exec, clone继承。对于进程设定memory policy之前分配的任何pages在设定之后保持原样
  • VMA级别
    未设定时,默认取基于进程的policy;

    • 主要作用于annoymous mapping(stack,heap)
    • 可在共享虚拟页面的任务上共享,比如线程
    • exec调用时不继承它,因为exec会丢弃父进程页面,重新创建
    • 如果任务试图在此VMA的子块内再次安装VMA policy,内核会将它分裂成多个VMA
    • 默认情况下,在安装此policy之前的page保持原样,除非mbind调用导致迁移
  • shared策略
    作用于memory objects,与VMA策略类似,也有不同之处

内存分配模式(mode)

  • NODE LOCAL (系统默认)
    在当前代码执行的地方分配内存
  • Interleave
    第一页分配在node 0,下一页在node 1,再下一页node 0,如此轮换。适合被多个线程访问的数据

进程的Numa分配可通过/proc/<pid>/numa_maps查看,单个node分配查看/sys/devices/system/node/node<X>/meminfo

进程会从父进程那继承分配策略,即默认的node local,且Linux 调度器会尽可能地在负载均衡的同时保持进程的cache不失效,也即尽可能让进程在靠近分配内存的node的CPU上运行。但,万一负载非常不均,调度器是会将进程迁移到其它numa node上的,这时的内存访问就变成了remote acess,性能会下降。kernel 3.8+支持将数据迁移到running node上

关于NUMA内存回收

当内存很低时,内核会考虑回收pages。具体回收哪些页取决于page类别,如mlock的page就不能回收。对于NUMA内存来讲,不同node剩余的内存很有可能不一样,当当前node不能分配所需内存而远程node可分配时,有两种策略:

  • 在local node上做回收
    但这会增加内核处理开销
  • 从远程分配

对于小型的numa系统,如2 nodes,内核默认第二种策略,对于大型numa系统(4 nodes以上),选择第一种。(这一点未在linux内核上确认,但存在这种可选策略是可以理解的)

通过查看/proc/sys/vm/zone_reclaim可知系统是否支持回收,它的值可以在启动时测量NUMA nodes之间的距离得到;如果被enabled,内核会尽可能少地执行此过程,且默认只回收unmapped page-cache pages,用户还可以通过/proc/sys/vm/min_unmapped_ratio来设置最小的回收比例来进一步限制reclaim频次;当然,也可以设置地更加aggressive ,比如允许剔除dirty pages, annoymous pages

关于first-touch策略[1]

这一点我第一次看到时感觉挺有趣。
我们要知道,真正发生page allocation的时刻是进程touch the page之时,第一次访问它会找不到,导致page fault,其导致了page分配。某个page它是属于某段内存的,而前面提到过,我们是可以针对一段内存来设置memory policy的,于是乎,若一些page如库程序的text segemnt被多个线程程序所共用,那么这些page应用的policy就是第一个对这段内存设置的policy。这种现象可能会对后来使用这段区域的进程产生意外的结果,比如进程A先启动,它设置libc.so的代码段在node 0上,进程B在node 1的CPU上启动,当B想设置libc.so放在node 1上时,结果因为libc.so已经被设置,进程B 不得不使用A 的策略而导致了远程访问。

感觉这种被迫的远程访问很容易发生,日后再具体了解linux是怎么解决的。

关于page moving

linux上有工具migratepages可以对一个进程的物理页面作迁移,但无论怎样是很难保证所有的page访问都是node local的,毕竟c库被大量共用。

关于numa 调度

linux kernel 3.8支持page在numa node上迁移。3.8前,调度器对进程page 分配是无感知的,迁移进程是基于对进程cache hotness来预估的,因此在3.8前,若想获得尽可能好的性能,应使用taskset, cpuset等工具将进程pin到特定的核上(c++框架seastar正是这种策略避免迁移的同时也实现了share-nothing);

截至2019/1/10 kernel 版本4.20.1,还不清楚page跨numa node迁移功能如何,改天再探寻~

关于多Numa节点下影响内存吞吐和延时的不是距离而是节点互连的反对称性[4]

这里的反对称性指的是各node之间的link具备不一样的物理性质,如传输比特位,单向还是双向等等。在这种node结构下,试验[4]证明正确放置线程和内存page对应用产生显著影响,其影响大于node之间的hop数,论文4提出的AsymSched算法可以使得CPU-CPU之间的内存通信带宽最大化(线程之间有共享数据)以及CPU-MEMORY的带宽最大化(当cache miss时,线程需从node上取pages)

原谅我讲述时时常夹带英文词汇,真的只是因为我认为它精准 [哭笑]。此文到这儿,后期再原位增添。

References

[1] Christoph Lameter, Ph.D. NUMA : An Overview , 2013.
[2] Kernel Documentation, NUMA memory policy. https://www.kernel.org/doc/html/v4.18/admin-guide/mm/numa_memory_policy.html

[3] NUMA架构的CPU -- 你真的用好了么?. http://cenalulu.github.io/linux/numa/

[4] Baptiste Lepers, Thread and Memory Placement on NUMA Systems: Asymmetry Matters, 2015

linux系统下如何查看cpu能同时跑几个线程_探讨基于Linux的NUMA系统相关推荐

  1. linux系统下cpu如何测试,Linux 系统下如何查看CPU个数

    该信息整理自网上,需要进一步学习和确认 cat /proc/cpuinfo 可以查看cpu个数 getconf LONG_BIT 查看是32位还是64位 例如: cat /proc/cpuinfo p ...

  2. Linux命令行如何查看cpu(lm_sensors)和显卡温度(nvidia-smi)

    Linux命令行如何查看cpu和显卡温度 lm_sensors,是一款基于linux系统的硬件监控的软件.可以监控主板,CPU的工作电压,温度等数据. 实际上sensors命令只是读取了/sys/cl ...

  3. linux 物理内存 分配,[linux物理内存分配]Linux系统下如何查看物理内存占用率

    你了解linux系统下如何查看物理内存占用率吗?跟着答.案.网 ZqNf.Com小编一起学习吧linux系统下如何查看物理内存占用率. linux系统下如何查看物理内存占用率方法 linux下看内存和 ...

  4. Linux下如何查看CPU信息, 包括位数和多核信息

    题记:今天看到一篇关于查看CPU和操作系统信息的文章,转过来和大家分享一下,O(∩_∩)O! 了解cpu架构   http://blog.csdn.net/wyzxg/archive/2009/12/ ...

  5. Linux下快速查看CPU使用情况的相关命令

    Linux下快速查看CPU使用情况比较常用的命令是free.top.ps.这篇文章来看下如何在Linux下检查服务器的CPU使用情况.我的Linux是Linux-Ubuntu-server-15.04 ...

  6. linux怎么64位,在linux下如何查看CPU是否支持64位

    在linux下如何查看CPU是否支持64位的方法是: # grep "flags" /proc/cpuinfo flags           : fpu tsc msr pae ...

  7. windows查看linux文件中文,Linux 系统下无法查看Windows 中创建的中文文件名

    标  题: Linux 系统下无法查看Windows 中创建的中文文件名 我是Linux初学者,在网上搜索了很久,经过多次尝试仍然无法解决问题,只好在这里发贴请教了,还望各位高手指点一下. 问题描述: ...

  8. linux 多线程ppn,Linux下如何查看CPU信息, 包括位数和多核信息

    Linux下如何查看CPU信息, 包括位数和多核信息 # uname -a Linux liuzhouping-laptop 2.6.28-14-generic #46-Ubuntu SMP Wed ...

  9. inux下如何查看CPU信息, 包括位数和多核信息

    inux下如何查看CPU信息, 包括位数和多核信息 # uname -a Linux euis1 2.6.9-55.ELsmp #1 SMP Fri Apr 20 17:03:35 EDT 2007 ...

最新文章

  1. linux实现命令解释器_想在Win10上安装Linux,只需一个命令即可实现
  2. 前端javascripts基础知识点猴子吃桃
  3. P6047-丝之割【斜率优化,dp】
  4. ORACLE1.21 PLSQL 01
  5. c++ primer 笔记 (二)
  6. spring 中构造Constructor、@Autowired、@PostConstruct、静态方法的执行顺序 (@PostConstruct 说明)
  7. php页面运用文本编辑器的实例,TP3.2.3框架使用CKeditor编辑器在页面中上传图片的方法分析...
  8. pythonATM,购物车项目实战8--通用函数的使用lib/common
  9. js把html转成json,js字符串转成JSON
  10. ewebeditor 3.8php漏洞,asp eWebEditor v3.8 列目录漏洞
  11. cadence allegro - PCB线路敷铜渲染
  12. 初学python数据结构-切片
  13. 【设计模式】设计模式 网站推荐
  14. Bable的基本使用
  15. 向 Dockerfile 传参 --build-arg 遇到的一些小坑
  16. VMware vCenter Server 8.0U1 发布 - 集中式管理 vSphere 环境
  17. Ping过程的完全解析
  18. 第四次作业——个人作业——必应词典软件案例分析
  19. iperf详细使用图文教程
  20. 【bzoj1123】[POI2008]BLO

热门文章

  1. 英特尔近日发布最新版实感™ SDK R5 (v7)
  2. SharePoint 2013 中如何使用Silverlight
  3. 对于随机变量的标准差standard deviation、样本标准差sample standard deviation、标准误差standard error的解释...
  4. 华为UPS“内外”兼修
  5. VC++中GlobalAlloc()、malloc()和new()函数之间区别
  6. ASP的DES加密解密
  7. java编程思想 入门_java编程思想学习(基础)
  8. 享有的意思是_“fuck you money”不是“x你钱”,真实意思却是这个
  9. 虚拟机服务器编号怎么查看,查看虚拟机的服务器地址
  10. 随机分配效果在task中的应用,公司内部代码片