当前位置: 首页 > 科技观察

系统性能调优:boundCPU

时间:2023-03-22 15:17:31 科技观察

从物理硬件角度支持超线程numa架构,将多个CPU封装在一起。这个包叫做socket套接字;Core是socket上一个独立的硬件单元;Hyper-ThreadingHT技术进一步提高了CPU的处理能力,以及操作系统看到的逻辑核心处理器的数量。每个硬件线程都可以由一个逻辑CPU寻址,因此处理器看起来有八个CPU。从操作系统的角度来看:CPU(s):8NUMAnode0CPU(s):0,4NUMAnode1CPU(s):1,5NUMAnode2CPU(s):2,6NUMAnode3CPU(s):3,7操作系统perspective.pngL1缓存分为两种,一种是指令缓存,一种是数据缓存。二级缓存和三级缓存不分离指令和数据。L1和L2缓存在第一个CPU内核中,L3是所有CPU内核共享的内存。L1、L2、L3离CPU越近,速度越小,速度越快,离CPU越远,速度越慢。后面是内存,内存后面是硬盘。让我们看看它们的一些速度:L1访问速度:4个CPU时钟周期L2访问速度:11个CPU时钟周期L3访问速度:39个CPU时钟周期RAM内存访问速度:107个CPU时钟周期如果要由CPU操作的数据在缓存中,则直接读取,称为缓存命中。命中缓存会带来很大的性能提升,所以我们的代码优化目标是提高CPU缓存命中率。在主流服务器上,一个CPU处理器有10到20个以上的物理内核。同时,为了提高服务器的处理能力,服务器上通常有多个CPU处理器(也叫多CPUSocket),每个处理器都有自己的物理核心(包括L1、L2缓存)、L3同时,缓存和连接内存通过总线连接不同的处理器。来自lscpu:root@ubuntu:~#lscpuArchitecture:x86_64CPU(s):32Thread(s)percore:1Core(s)persocket:8Socket(s):4L1dcache:32KL1icache:32KL2cache:256KL3cache:20480KNUMAnode0CPU(s):0-7NUMAnode1CPU(s):8-15NUMAnode2CPU(s):16-23NUMAnode3CPU(s):24-31你可能会注意到三级缓存比一二级缓存大很多倍,因为现在的CPU都比较Core,每个核心都有自己的一级和二级缓存,但三级缓存由CPU上的所有核心共享。但是,有一点需要注意:如果应用程序先运行在一个Socket上,并将数据保存在内存中,然后被调度到另一个Socket上运行,此时,当应用程序执行内存再次访问,需要访问之前Socket上连接的内存,这种访问属于远程内存访问。与访问直接连接到套接字的内存相比,远程内存访问会增加应用程序的延迟。常用的性能监控工具在Linux系统下,常用的CPU和内存子系统性能调优的性能监控工具有top、perf、numactl。1)top工具top工具是最常用的linux性能监控工具之一。您可以通过顶级工具监控流程和整体系统性能。top查看整个系统的资源使用情况,top后输入1,查看每个逻辑核心cpu的资源使用情况top-p$PID-H,查看一个进程中所有查看的CPU资源使用情况,top后输入F选择P选项,在线程执行过程中检查该线程是否被调度到其他CPU上执行。当上下文切换过多时,需要注意。2)perf工具perf工具是一个非常强大的Linux性能分析工具,通过它可以获取进程内调用,资源消耗,查找分析热点函数。以CentOS为例,使用如下命令安装perf工具:perftop查看占用CPU时钟最多的函数或指令,可以用来寻找热点函数。perf-grecord--sleep1-p$PID记录1s内进程的系统调用。perf-glatency--sortmax查看上一步记录的结果,安排延迟排序。perfreport查看记录3)numactl工具numactl工具可以用来查看当前服务器的NUMA节点配置和状态。通过这个工具,可以将进程绑定到指定的CPU核心上,指定的CPU核心就会运行相应的进程。以CentOS为例,使用如下命令安装numactl工具:numactl-H查看当前服务器的NUMA配置。numastat查看当前NUMA运行状态。优化方法(1)NUMA优化,减少跨NUMACPU内核访问内存,不同NUMA在同一位置访问内存,性能不同。内存访问延迟从高到低依次为:cross-CPU>cross-NUMA,非cross-CPU>withinNUMA。因此,应用程序在运行时,需要尽可能避免跨NUMA访问内存,可以通过设置线程的CPU亲和性来实现。常用的修改方法如下:(1)将设备中断绑定到特定的CPU核上。可以通过以下命令绑定:echo$cpuNumber>/proc/irq/$irq/smp_affinity_list示例:echo0-4>/proc/irq/78/smp_affinity_listecho3,8>/proc/irq/78/smp_affinity_list(2)vianumactl启动程序,比如下面的启动命令表示启动程序./mongod,mongo只能运行在CPUcore0到core7(-C控制)。numactl-C0-7./mongod(3)可以使用taskset命令绑定一个程序在一个核心上运行。taskset-c0./redis-server(4)通过C/C++代码中的sched_setaffinity函数设置线程亲和性。(5)许多开源软件已经支持在内置配置文件中修改线程亲和性。例如Nginx可以通过修改nginx.conf文件中的worker_cpu_affinity参数来设置Nginx的线程亲和性。绑定核心注意事项在CPUNUMA架构下,CPU核心的编号规则不是先编译一个CPUSocket中的所有逻辑核心,然后再对下一个CPUSocket中的逻辑核心进行编码。每个CPUSocket中每个物理核心的第一个逻辑核心依次编号,然后对每个CPUSocket中物理核心的第二个逻辑核心依次编号。需要注意的是,多个进程需要亲和绑定。一定要注意NUMA架构下CPU核心的编号方式,以免绑定错误的核心。本文转载自微信公众号《运维开发故事》,可通过以下二维码关注。转载本文请联系运维开发故事公众号。