计算化学公社

 找回密码 Forget password
 注册 Register
Views: 7200|回复 Reply: 1
打印 Print 上一主题 Last thread 下一主题 Next thread

[并行运算] NUMA策略对Gaussian运算速度影响的小研究

[复制链接 Copy URL]

903

帖子

37

威望

5324

eV
积分
6967

Level 6 (一方通行)

本帖最后由 ggdh 于 2020-10-23 22:04 编辑

先介绍一下NUMA
NUMA就是非均匀内存访问 (Non-uniform memory access),简单的说就是当一个主板上插了多块CPU时,每块CPU访问靠近自己的内存速度快,而访问远离自己的内存速度慢,如下图所示

图片来自http://cenalulu.github.io/linux/numa/
这个图表示一个主板上插了4片CPU,可以说这个机器中有4个NUMA节点(NUMA node),每个节点由一个cpu和靠近它的内存组成。
NUMA策略就是指是让一个NUMA节点来算一个任务,还是让多个NUM节点来算一个任务。
显然,单任务使用全部核心运算的情况下不存在NUMA的问题。
但是如果是多任务同时运行——任务很多时为了提高计算效率的情形,或者是单任务只使用了部分CPU时——CPU不是瓶颈,内存是瓶颈的情形。NUMA策略就能产生影响。
具体的策略和实现方式在后面有详细描述。

结论
我怕你们看这么长的文章到最后才发现结论没什么用并且还要做题后产生想打我的冲动,我就先把结论放这
1.在满载情况下,无论是单任务,还是多任务,NUMA配置对效率基本没有影响。多任务情况下,把任务局域在NUMA节点上会快稍微一丢丢。
2.在非满载情况下,把任务尽可能的分配在更多的NUMA节点上能带来最大的速度提升,这种提升大概在使用一半的系统资源时最明显。
3.NUMA效应主来的原因是内存带宽和内存延迟共同导致的,因此可以预见对于费内存的任务,NUMA带来的影响会比较大。
4.在进行并行效率测试的时候,最好考虑NUMA配置的问题,否则会因为nprocshared的随机分配cpu导致测试结果的随机波动。
5.以上结论是基于双路系统和G16AVX2的测试结果,其他硬件平台和程序的情况有待进一步研究.

相关链接
通过设置CPU内核绑定降低ORCA同时做多任务的耗时
该文结论和本文一样,不过这篇文献是从cpu绑定的角度来讨论的,本文引入了NUMA的概念,有利于深入理解这个现象。
g09/g16速度测试脚本xbench 2.0 【更新2.0,支持numa】
这个测试脚本中加入了对NUMA的支持。


验证自己机器上的NUMA情况
Intel® Memory Latency Checker v3.9下载工具可以测试具体的内存访问速度。下载完成之后解压,然后运行
  1. sudo ./mlc
复制代码
他会给出一系列结果
首先是访问内存的延迟:

可以看到有两个NUMA节点(双路主板),NUMA节点中的cpu访问其他节点内存的延迟大概是访问自己节点上内存的两倍(这里是epyc7742的数据,E5-2699V4是80/130),说明确实是numa构架
然后可以看内存带宽:

这里列出了不同的读写比例下的内存带宽,这个系统是16通道X32GB,内存带宽达到了280GB/s左右(Intel平台8通道X16GB的带宽是100GB左右)
然后是不同带宽下的内存延迟:

这里可以看到内存带宽负荷对内存延迟的影响(NUMA节点内访问)
可以看到随着内存带宽负荷增大,内存延迟也会明显增大到接近3.5倍(E5-2699V4平台是增大3.3倍)

使用numactl设置NUMA
一般linux系统会自动支持NUMA,使用
  1. dmesg | grep NUMA
复制代码
查看系统对numa的支持是否开启
我们可以人为配置NUMA,这需要安装numactl命令
a)安装
  1. yum install numactl    #centos
  2. sudo apt-get install numactl    #ubuntu
复制代码

b)查看numactl的默认设置
使用命令
  1. numactl --hardware
复制代码
查看numa硬件

可以看到两个NUMA节点中的cpu编号,和对应的内存大小
使用命令
  1. numactl -s
复制代码
查看当前的numa策略,下面详细介绍一下numa策略,以及更改策略的方法

c)使用不同的numa策略来运行程序
可以使用numactl命令来配置某个程序运行时的资源使用,比如:
  1. numactl --cpunodebind=0 --membind=0   g16 test.gjf
复制代码
使用0号numa节点上的cpu和0号numa节点上的内存来运行一个g16任务
numa策略大概可以分为两类,分别是cpu策略和内存策略,其中设置cpu策略的选项有:
--cpunodebind=0             设定某个numa节点上的cpu,默认是--cpunodebind=all也就是不限制numa节点
-C=0,20                          设定具体的cpu核心(这里是0和20号cpu核心),这个有点像gaussian中的%cpu,但是这里没有绑定核心,只是分配这两个核心给程序。
内存策略的选项有:
--localalloc                      只从当前NUMA节点上分配内存
--membind=1                 只从1号NUMA节点上分配内存
--preferred=0                 从0号NUMA节点上分配内存,如果失败了(内存不够了)就尝试其他node
--interleave=0,1             从0,1号两个NUMA节点上轮流分配内存

d) 查看某个进程的NUMA资源使用情况状态
使用numactl运行g16后,输入
  1. numastat -p l502.exe
复制代码
查看l502.exe这个进程(Gaussian自洽场)在不同numa节点上的内存占用状态,输入
  1. ps -U $USER -L -o pid,cpuid,pcpu,comm | grep l502 | sort -nk 2
复制代码
查看某个进程具体在哪些cpu core 上运行,占用率是多少,其中l502是进程名称,也可以改成进程的pid

NUMA策略对Gaussian运算速度的影响
设置G16的numa环境有三种方法
1,使用上文提到的numactl命令。
2,使用G16当中的%cpu设置,绑定到cpu,也自然绑定到numa节点了。只是无法进行内存的绑定,但默认的numa策略是优先使用近距离的内存。
3,使用我开发的测试脚本xbench,从2.0版本开始通过numactl命令支持numa设定。
下面测试具体例子时使用1,3两种方案。其中xbench用法看不明白的同学可以先去xbench的原贴去看看。

有以下几种NUMA策略
local:
尽量使用少的NUMA节点进行计算,把一个NUMA节点占完之后再开始使用下一个NUMA节点,运行方法:
  1. numactl --cpunodebind=1 --membind=1 g16 test397.inp
复制代码
由于一个NUMA节点对应于一块物理cpu,假设这里的一个CPU有22个核心,而G16任务中设置的也是22核并行,因此上面设定使得这个任务正好占满一个NUMA节点,另一个NUMA完全闲置。
或者
  1. numactl -C 0,1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21 --membind=1 g16 test397.inp
复制代码
这里指定了具体的cpu核心id,0-21正好对应于一块CPU中的全部核心,或者
  1. xbench.sh -n 11 -t 3 -r 3 -N loc
复制代码
这个脚本中同时运行了3个11核的任务,其中两个占满了一个NUMA节点,另外一个占了一半的NUMA节点。

distributed:
把每个任务尽量均匀的分布在两块CPU上
  1. numactl -C 0,1,2,3,4,5,7,8,9,10,22,23,24,25,26,27,28,29,30,31,32 g16 test397.inp
复制代码
其中0-10号核心属于0号cpu,22-32号核心属于1号cpu,或者
  1. xbench.sh -n 4 -t 4 -r 3 -N dist
复制代码
这里同时运行4个4核心任务,其中第一个任务占用0,1,22,23号核心,第二个任务占用2,3,24,25号核心,依此类推。。。

remote:
不用靠近自己内存,偏要用另一块cpu上的内存(这种反人性的设定纯粹是为了测试用)
  1. numactl --cpunodebind=0 --membind=1 g16 test397.inp
复制代码
xbench不支持这种反人性的设定。。。

semi:
只在同时运行多任务下适用,单个任务集中在一个NUMA 节点上,而多个任务尽可能的分布在不同的NUMA节点上。
numactl一次只能运行一个任务,因此需要同时写多行numactl命令才能完成这个操作。
  1. xbench.sh -n 11 -t 2 -r 3 -N semi
复制代码
这会使得两个11核的任务分别运行在两个的NUMA节点上。

下面看具体的测试情况
a)普通DFT任务
运行环境:XEON E5-2699V4 (22 core) X 2,16G内存 X 8,G16 AVX2版本
输入文件:Gaussian TEST397
关键词:#p b3lyp 3-21g force test scf=novaracc int(fine,acc2e=10)
测试了在local,distributed,和remote三种设置下,单任务运行和双任务同时运行两种情况。

结论:
  • 单任务运行时,把任务集中到一个NUMA节点,比把任务平均分配给两个NUMA节点要慢,这可能是因为一个NUMA节点内存带宽有限(4通道),以及只用一个NUMA节点时内存带宽的负载更大,导致内存延迟变高。
  • remote情况下,运算速度均有明显变慢,说明内存延迟的对计算速度的影响比较显著(对于这块cpu,remote内存延迟大概是local的1.5倍)
  • 同时运行两个任务时,local和distributed区别不大,local反而要稍微低一点点,这是因为前面提到的内存带宽负载导致的内存延迟提高效应在两种情况下变成一样了。并且local的双任务运行耗时和单任务运行耗时一样。这充分说明两个NUMA节点各算各的,互不干涉。


b)freq任务
运行环境和上面的例子一样,只是把关键词改为
#p b3lyp 3-21g freq test scf=novaracc int(fine,acc2e=10)

结论:
和上面一样,由于freq任务更吃内存,所以这里的NUMA效应更加显著了。
我之前测并行效率时,发现跑freq 或者td任务时,测出来的曲线总是歪歪扭扭的(高斯软件并行效率再测(2017.1)
就是因为当时设置核心时,用的是%nprocshared=X,而这这样的设置会导致cpu随机分布。由于freq对NUMA很敏感,所以测出来的线也就随机扭曲了。。。

c)不同NUMA策略下的并行效率测试
运行环境:EPYC 7742 (64 core) X 2,32G内存 X 16,G16 AVX2版本
输入文件:Gaussian TEST397
关键词:#p b3lyp 3-21g force test scf=novaracc int(fine,acc2e=10)
下面两组并行效率的测试,左边是单任务逐步增加核数,右边是单个任务控制到8核,逐步增加任务数。

在local状态下,都可以明显的看到在64核处出现一个拐点,说明第一个NUMA核心被用完,开始启动第二个NUMA节点时,速度获得了提升。
各种NUMA配置在满载的状态下基本都殊途同归了(多任务的local会快一丢丢,大概时因为满载状态下,local可以节省NUMA节点之间通讯的成本)

d)不同NUMA策略下的Freq并行效率测试
运行环境和上面的例子一样,只是把关键词改为
#p b3lyp 3-21g freq test scf=novaracc int(fine,acc2e=10)
每个任务32核,在不同的NUMA策略下增加同时运行的任务数,最后统计每个任务的平均耗时。

能看到这里的同学不容易啊,作为奖励,这个就当作思考题了(雾
请解释为什么不同的NUMA策略下,耗时的情况如图所示。




评分 Rate

参与人数
Participants 3
威望 +2 eV +10 收起 理由
Reason
ghifi37 + 5 精品内容
sobereva + 2 精品内容
biogon + 5 とてもいい!

查看全部评分 View all ratings

1236

帖子

1

威望

3495

eV
积分
4751

Level 6 (一方通行)

2#
发表于 Post on 2020-10-15 17:59:15 | 只看该作者 Only view this author
两个任务同时挤在一个核心上抢内存带宽了吧,没想到DFT也会影响如此大

本版积分规则 Credits rule

手机版 Mobile version|北京科音自然科学研究中心 Beijing Kein Research Center for Natural Sciences|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949号-1 )|网站地图

GMT+8, 2024-11-23 15:47 , Processed in 0.195179 second(s), 25 queries , Gzip On.

快速回复 返回顶部 返回列表 Return to list