假设我们想控制线程如何被分配到处理器核心,或者选择我们想分配数据的位置,那么numactl命令就适合此类任务。在这篇文章中,我们讨论了如何使用numactl命令执行此类操作。
现代处理器采用*非统一内存访问(NUMA)*的方式进行硬件设计。
有时我们想控制线程如何被分配到处理器内核上,以避免使用超线程,而是使用硬件线程,或者确保一个任务不会频繁迁移。
在Linux中,numactl被用来完成这样的任务,它能够选择我们想要执行任务的内核,也能够选择我们想要分配数据的地方,这要感谢两个策略,NUMA调度策略和NUMA内存放置策略。
语法如下:
numactl [ --interleave nodes ] [ --preferred node ] [ --membind nodes ] [ --cpunodebind nodes ] [ --physcpubind cpus ] [ --localalloc ] command {arguments ...}
各种策略的设置是:
--interleave=nodes, --i nodes设置内存交错策略,内存将使用循环机制在节点上分配,当它不能在当前的交错上分配时,目标将回到其他节点上。
我们可以指定*'all',这将意味着当前集合中的所有节点。
要指定节点,我们写n,n,n或n-n,n-n,
例如0-4,指定0到4的节点。
要指定相对节点,我们可以写,+n,n,n或+n-n或+n,n*-n,其中*+*表示节点数字是相对于进程在当前cpuset中允许的节点集合而言的。
反过来说,我们可以写*!n-n来表示除n-n*节点之外的所有节点。
--preferred=node指定我们希望在可能的情况下分配到指定的节点上,否则就退到其他节点上。这里也可以使用相对符号。
--membind=nodes,-m nodes表示我们只从节点分配内存。当节点上没有足够的内存可用时,分配将失败。
--cpunodebind=nodes, -N nodes意思是只在指定节点的CPU上执行命令。节点可能由几个CPU组成。
--physcpubind=cpus, -C cpus意味着只在指定的cpus上执行进程。这将采用*/proc/cpuinfo*文件中描述的cpu编号或相对于当前cpuset的相对cpus。
要查看活动的cpus列表,我们写道:
cat /proc/cpuinfo
指定cpus类似于之前描述的关于*-interleave=nodes的规范,-i nodes*
--localalloc -l,当我们想在当前节点上进行分配时使用:
numactl [ --huge ] [ --offset offset ] [ --shmmode shmmode ] [ --length length ] [ --strict ] [ --shmid id ] --shm shmkeyfile | --file tmpfsfile [ --touch ] [ --dump ] [ --dump-nodes ]
--huge, 用于在创建SYSV共享内存段时使用巨大的页面。
--offset offset, 用于指定共享内存段的偏移量,例如m代表MB,g代表GB,k代表KB,默认为0,如果没有指定,则以字节为单位。
--shmmode shmmode, 在 --shmid 或 --shm 之前有效,在创建共享内存段时,我们将其设置为shmmode数字模式。
--length长度,指定新段的长度,例如m代表MB,k代表KB,g代表GB,默认值是字节。
--strict, 当共享内存段中具有策略的区域中的一个页面与一个冲突的策略发生故障时,产生一个错误。默认情况下,这被默默地忽略。
--shmid id, 用于创建或使用一个具有指定数字id的共享内存段。
--shm shmkeyfile, 用来创建或使用一个共享内存段,其ID是用shmkeyfile的ftok生成的。
--file tmpfsfile, 为tmpfs或hugetlbfs中的一个文件设置策略。
--touch, 触摸页面,以便尽早执行策略。当应用程序映射和访问一个页面时,策略就会被应用。默认情况下,这些页面不被触及。
--dump, 用于指定范围内的转储策略。
--dump-nodes, 转储指定范围内的所有节点。
要查看系统的NUMA架构,请写:
numactl --hardware
要查看当前进程的NUMA策略,请写:
numactl --show
要查看NUMA内存命中率统计,请写。
cat /sys/devices/system/node/node*/numastat
要在cpu 0上使用节点0和1的内存运行一个程序testProg,我们写:
numactl --cpubind=0 --membind=0,1 testProg
要在当前cpu组的cpu0-4和8-12上运行一个应用程序testApp,我们写道:
numactl --physcpubind=+0-4,8-12 testApp arguments
为了运行一个进程bigProcess并在所有CPU上交错使用其内存,我们写道:
numactl --interleave=all bigProcess arguments
要在首选节点1上运行一个进程,并显示结果状态,我们写道:
numactl --preferred=1 numactl --show
要在节点4上运行一个进程并在节点4和5上分配内存,我们写道:
numactl --cpubind=4 --membind=4,5 process
要在numa节点2、3、4上执行process:
numactl -N 2,3,4 -l process
numactl是一个Linux函数,它以指定的NUMA调度或内存放置策略运行进程。
它将进程与Linux NUMA超级计算机上的处理器绑定。
使用numactl 的目的是将进程限制在一个numa池或CPU节点上,而不是特定的CPU核。
通过numactl,我们可以绑定CPU的内存位置,以防止跨NUMA池/内存节点的跳转。