系统性能优化-2 CPU

其实除了 CPU 的频率,多核架构以及多 CPU 架构对系统运行的性能也是很大影响的,那么该如何充分利用 CPU 呢?

CPU 架构

首先介绍一下当前主流的 CPU 架构,现在的系统基本都是多 CPU,一个 CPU 处理器中一般有多个运行核心,我们把一个运行核心称为一个物理核每个物理核都可以运行应用程序。每个物理核都拥有私有的一级缓存(Level 1 cache,简称 L1 cache),包括一级指令缓存和一级数据缓存,以及私有的二级缓存(Level 2 cache,简称 L2 cache)。同时,一个 CPU 上的所有物理核共享一个三级缓存。

image-20250617213848204

Centos 可以使用 lscpu 查看系统 CPU 信息

[root@VM-16-11-centos zwj]# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                2
On-line CPU(s) list:   0,1
Thread(s) per core:    1
Core(s) per socket:    2
Socket(s):             1
NUMA node(s):          1
Vendor ID:             GenuineIntel
CPU family:            6
Model:                 94
Model name:            Intel(R) Xeon(R) Gold 6148 CPU @ 2.40GHz
Stepping:              3
CPU MHz:               2394.364
BogoMIPS:              4788.72
Hypervisor vendor:     KVM
Virtualization type:   full
L1d cache:             32K
L1i cache:             32K
L2 cache:              4096K
L3 cache:              28160K
NUMA node0 CPU(s):     0,1

程序在执行时,会先将内存中的数据载入三级缓存,再进入每颗核心独有的二级缓存,最后进入最快的一级缓存,之后才会被 CPU 使用。

缓存比内存的访问速度要快很多,访问内存要100个时钟周期以上,一级缓存只需要4~5个时钟周期,二级缓存大约12个时钟周期,三级缓存大约30个时钟周期。因此如果 CPU 所要操作的数据可以命中缓存,会带来一定的性能提升。

NUMA 架构

一个 CPU 的结构我们清楚了,但现在的系统基本都是多 CPU(也称为多 CPU Socket),CPU 之间通过总线连接,如下图所示:

image-20250617214720473

在多 CPU 架构上,应用程序可以在不同的 CPU 上执行,如果应用程序先在一个 Socket 上运行,并且把数据保存到了内存,然后被调度到另一个 Socket 上运行,此时,应用程序再进行内存访问时,就需要访问之前 Socket 上连接的内存,这种访问属于远端内存访问。和访问 Socket 直接连接的内存相比,远端内存访问会增加应用程序的延迟。

在多 CPU 架构下,一个应用程序访问所在 Socket 的本地内存和访问远端内存的延迟并不一致,所以,我们也把这个架构称为非统一内存访问架构(Non-Uniform Memory Access,NUMA 架构)

所以 CPU 架构对应用程序的运行主要有以下影响:

  • cpu 缓存访问速度远远大于内存,因此尽量缓存命中,多利用缓存
  • NUMA 架构可能会出现远端内存访问的情况,这会直接增加应用程序的执行时间

提升缓存命中率

Centos 运行 lscpu

[root@VM-16-11-centos zwj]# lscpu
Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
L1d cache:             32K
L1i cache:             32K
L2 cache:              4096K
L3 cache:              28160K
NUMA node0 CPU(s):     0,1

可以看到 L1 cache 并不是单独的,而是分为 L1d cache 和 L1i cache,也就是 数据缓存 和 指令缓存,因此提高缓存命中率也需要分别考虑

数据缓存

思考这样一个场景,有一个二维数组需要进行一次遍历

int arr[10][10];for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; i++) {printf("%d", arr[i][j])}
}
int arr[10][10];for (int i = 0; i < 10; i++) {for (int j = 0; j < 10; i++) {printf("%d", arr[j][i])}
}

不要思考这个场景是否合理,比如需要遍历一个数组把所有值加入到一个 set 中,思考这两种方式的执行速度,其实方式1是远优于方式2的(如果是 Python,会由于数组的设计效果没那么明显)。

原因是 CPU 其实有 Cache Line 的概念,CPU 在读取数据时会一次性读取 Cache Line 大小的数据到缓存中,而我们又知道数组在内存中是紧密排放的

arr[0][0] arr[0][1] arr[0][2]
arr[1][0]    
arr[2][0]    

如果按照第一种方式遍历,就可以利用 CPU 缓存加快访问

Linux 可以通过 cat /sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size 查看 Cache Line 大小

[root@VM-16-11-centos zwj]# cat /sys/devices/system/cpu/cpu0/cache/index1/coherency_line_size 
64

Cache Line 在 nginx、redis 的设计中都有所体现:

  • nginx 使用哈希表存放域名、http头部信息,哈希表里桶的大小如 server_names_hash_bucket_size,它默认就等于 CPU Cache Line 的值。由于所存放的字符串长度不能大于桶的大小,所以当需要存放更长的字符串时,就需要修改桶大小,但 Nginx 官网上明确建议它应该是 CPU Cache Line 的整数倍。
  • redis 的 sds 中,embstr 的 44 字节,其实也是 CPU Cache Line 的体现,当 robj + 字符串 + ‘\0’ 的长度不超过 64 时,此时编码就是 embstr,在读取到 robj 时就直接取到了字符串数据,无需再次访问内存。

执行 perf stat 可以统计出进程运行时的系统信息(通过 -e 选项指定要统计的事件,如果要查看三级缓存总的命中率,可以指定缓存未命中 cache-misses 事件,以及读取缓存次数 cache-references 事件,两者相除就是缓存的未命中率,用 1 相减就是命中率。类似的,通过 L1-dcache-load-misses 和 L1-dcache-loads 可以得到 L1 缓存的命中率)

指令缓存

上面只是介绍了提高数据缓存的命中率,还有指令缓存的命中率

假如有一个数组,里面是一些 0~255 的数字,需要找出其中 < 128 的置为 0 并进行排序,方法1是先找到对应数据并置为0再排序,方法2是先排序再置为0。

for(i = 0; i < N; i++) {if (array [i] < 128) array[i] = 0;
}
sort(array, array + N);
sort(array, array + N);
for(i = 0; i < N; i++) {if (array [i] < 128) array[i] = 0;
}

先排序的方法速度其实是要更快的,原因是因为循环中有大量的 if 条件分支,而 CPU含有分支预测器。当代码中出现 if、switch 等语句时,意味着此时至少可以选择跳转到两段不同的指令去执行。如果分支预测器可以预测接下来要在哪段代码执行(比如 if 还是 else 中的指令),就可以提前把这些指令放在缓存中,CPU 执行时就会很快。当数组中的元素完全随机时,分支预测器无法有效工作,而当 array 数组有序时,分支预测器会动态地根据历史命中数据对未来进行预测,命中率就会非常高

绑核

多 CPU 和多核心是不可避免的,为了缓解 NUMA 及应用程序重新调度后需要再次加载数据到 CPU 缓存的问题,操作系统提供了绑核指令,ls cpu 指令可以查看每个 CPU 对应的核心编号,可以使用 taskset 命令行指令在启动时将应用程序与 CPU 进行绑定,也可以使用不同语言的 API (如sched_setaffinity)通过系统调用在程序代码中设置进程的 CPU 亲和性。此外,Perf 工具也提供了 cpu-migrations 事件,它可以显示进程从不同的 CPU 核心上迁移的次数。

绑核是把双刃剑,如果你的程序有很多的后台线程,例如 redis 需要子线程生成 rdb、aof 重写、删除过期 key,就会导致子进程、后台线程和主线程竞争 CPU 资源,一旦子进程或后台线程占用 CPU 时,主线程就会被阻塞,导致 Redis 请求延迟增加。当然也有缓解的办法,比如让程序绑定一个具有多个逻辑核心的核,可以在一定程度上缓解 CPU 资源竞争。

不过 Redis 6 好像已经提供了支持 CPU 核绑定的配置操作了~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/84307.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/84307.shtml
英文地址,请注明出处:http://en.pswp.cn/web/84307.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker Pull 相关配置指南

在Docker环境中&#xff0c;docker pull命令用于从Docker镜像仓库拉取镜像。为了确保Docker镜像能够快速、稳定地拉取&#xff0c;配置 docker pull相关的设置是非常重要的。本文将详细介绍如何配置Docker以优化 docker pull操作&#xff0c;涵盖镜像源配置、登录私有仓库、网络…

Python的Matplotlib库:从入门到精通的数据可视化实战指南

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 持续学习&#xff0c;不断…

CentOS查日志

在 CentOS 系统中&#xff0c;查看日志是系统维护和故障排查的重要技能。以下是常用的日志查看方法和工具&#xff1a; 1. 基本日志位置 CentOS 使用systemd管理服务&#xff0c;主要日志存储在&#xff1a; /var/log/messages&#xff1a;系统主日志/var/log/secure&#x…

Linux运维新人自用笔记(用虚拟机Ubuntu部署lamp环境,搭建WordPress博客)

内容全为个人理解和自查资料梳理&#xff0c;欢迎各位大神指点&#xff01; 每天学习较为零散。 day20 一、./configure 脚本命令 ./configure 是 Unix/Linux 系统中用于配置软件源代码的脚本命令&#xff0c;通常用于为后续的 make 和 make install 准备编译环境。 选项作…

JetBrains 2025 全家桶 包含 IDEA、WebStorm、DataGrip、Pycharm、CLion、GoLand、PhpStorm

JetBrains 2025 全家桶 11合1 包含&#xff1a;IDEA、WebStorm、DataSpell、DataGrip、Pycharm、RustRover、CLion、Rider、PhpStorm、RubyMine、GoLand。 原文地址&#xff1a;JetBrains 2025 全家桶 11合1 含 IDEA、PyCharm、DataGrip、WebStrom、GoLand、CLion、PhpStorm、D…

【一手实测】字节豆包 1.6 + Trae + 火山 MCP + FaaS:AI云原生 Agent 开发部署全流程体验!

原创 Aitrainee AI进修生 2025年06月13日 16:42 湖南 标题已修改 缘起 —— 火山引擎在 2025 原动力大会上&#xff0c;也端出了自家的豆包大模型&#xff1a;Doubao-Seed-1.6 系列。 这三兄弟都支持文本、图片、视频输入&#xff0c;都带着 256K 的长上下文。 Doubao-Seed-…

Vulkan学习笔记8—顶点输入描述与顶点缓冲

一、着色器代码更新及构建时自动编译着色器脚本 用内存中的顶点缓冲区替换顶点着色器中硬编码的顶点数据 之前的顶点着色器&#xff1a; #version 450layout(location 0) out vec3 fragColor;// 顶点数据硬编码 vec2 positions[3] vec2[](vec2(0.0, -0.5),vec2(0.5, 0.5),…

Day04_数据结构(栈链栈循环队列)

01.栈 main.c #include "stack.h" int main() { stack_p S(stack_p)create_stack(); //1.入栈 …

PyTorch 的 CUDA GPU 支持 · 安装五条铁律(最新版 2025 修订)(适用于所有用户)

相关参考资料&#xff08;往期博客&#xff09;&#xff1a; 是否需要预先安装 CUDA Toolkit&#xff1f;——按使用场景分级推荐及进阶说明-CSDN博客 太方便&#xff0c;WIN系统CUDA12.4下使用conda便捷管理虚拟环境中的不同版本的CUDA、cuDNN、PyTorch-CSDN博客 好消息&#…

Django构建简易视频编辑管理系统

Django构建简易视频编辑管理系统 以下是基于Django构建简易视频编辑管理系统的可运行代码框架&#xff0c;包含核心功能模块和实现逻辑。该系统支持视频上传、基本剪辑操作和管理功能。 环境准备 安装必要依赖包&#xff1a; pip install django pillow moviepy django-cri…

Java求职者面试题详解:计算机网络、操作系统、设计模式与数据结构

Java求职者面试题详解&#xff1a;计算机网络、操作系统、设计模式与数据结构 第一轮&#xff1a;基础概念问题 1. 请解释TCP和UDP的区别。 2. 什么是操作系统&#xff1f;它的主要功能是什么&#xff1f; 3. 请解释设计模式中的单例模式&#xff0c;并给出一个实际应用的例…

【mysql】docker运行mysql8.0

背景 mariadb10.5.8报错&#xff1a;Error 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ‘LIMIT ?’ at line 1 所以更换为mysql8.0.39试试 docker run启动…

C#实现语音预处理:降噪/静音检测/自动增益

无论是在音视频录制系统&#xff0c;还是音视频通话系统、或视频会议系统中&#xff0c;对从麦克风采集到的说话的声音数据进行预处理&#xff0c;都是是非常必要的。 语音数据预处理主要包括&#xff1a;​​降噪&#xff08;Noise Reduction&#xff09;、静音检测&#xff0…

组合模式Composite Pattern

模式定义 又称整体-部分模式 组合多个对象形成 树形结构 以表示“整体-部分”的结构层次 组合模式对单个对象&#xff08;即叶子对象&#xff09;和组合对象&#xff08;即容器对象&#xff09;的使用具有一致性对象结构型模式 模式结构 Component&#xff1a;抽象构件Leaf&a…

商代大模型:智能重构下的文明曙光与青铜密码

引言&#xff1a;技术奇点的历史想象 在人类文明的长河中&#xff0c;技术的进步始终是推动社会变革的核心动力。从青铜冶炼到文字发明&#xff0c;从农业革命到工业革命&#xff0c;每一次技术飞跃都重塑了人类对世界的认知与生存方式。而如今&#xff0c;人工智能的崛起正以…

【Python】python系列之函数作用域

Python 系列文章学习记录&#xff1a; Python系列之Windows环境安装配置_开着拖拉机回家的博客-CSDN博客 Python系列之变量和运算符_开着拖拉机回家的博客-CSDN博客 Python系列之判断和循环_开着拖拉机回家的博客-CSDN博客 Python系列之字符串和列表_开着拖拉机回家的博客…

Unity UI 核心类解析之Graphic

&#x1f9f1; Unity UI 核心类解析&#xff1a;Graphic 类详解 一、什么是 Graphic&#xff1f; 在 Unity 的 UI 系统中&#xff0c;Graphic 是一个抽象基类&#xff0c;继承自 UIBehaviour 并实现了 ICanvasElement 接口。它是所有可以被绘制到屏幕上的 UI 元素的基础类。 …

【Elasticsearch】文档迁移(Reindex)

文档迁移 1.为什么要进行 reindex 操作2.Reindex 操作的本质3.实际案例3.1 同集群索引之间的全量数据迁移3.2 同集群索引之间基于特定条件的数据迁移3.2.1 源索引设置检索条件3.2.2 基于 script 脚本的索引迁移3.2.3 基于预处理管道的数据迁移 3.3 不同集群之间的索引迁移3.4 查…

WordPress 区块版面配置指南

WordPress 的区块编辑器(Gutenberg)提供了灵活的版面配置选项&#xff0c;以下是主要配置方法&#xff1a; 基本区块布局 添加区块&#xff1a;点击””按钮或按”/”键快速插入区块 常用内容区块&#xff1a; 段落(Paragraph) 标题(Heading) 图像(Image) 画廊(Gallery)…

TensorFlow基础之理解张量

2.理解张量 张量&#xff08;Tensors&#xff09;介绍 张量是物理和工程领域的基础数学结构。但是过去张量很少在计算机科学里使用。它与离散数学和逻辑学有更多的联系。随着机器学习的出现&#xff0c;这种状态开始显著的改变&#xff0c;成为连续向量的计算基础。现代机器学…