CSDN|如何写出让 CPU 跑得更快的代码?( 四 )
那访问 array[0][0] 元素时 , CPU 具体会一次从内存中加载多少元素到 CPU Cache 呢?这个问题 , 在前面我们也提到过 , 这跟 CPU Cache Line 有关 , 它表示 CPU Cache 一次性能加载数据的大小 , 可以在 Linux 里通过 coherency_line_size 配置查看 它的大小 , 通常是 64 个字节 。
本文插图
也就是说 , 当 CPU 访问内存数据时 , 如果数据不在 CPU Cache 中 , 则会一次性会连续加载 64 字节大小的数据到 CPU Cache , 那么当访问 array[0][0] 时 , 由于该元素不足 64 字节 , 于是就会往后顺序读取 array[0][0]~array[0][15] 到 CPU Cache 中 。 顺序访问的 array[i][j] 因为利用了这一特点 , 所以就会比跳跃式访问的 array[j][i] 要快 。
因此 , 遇到这种遍历数组的情况时 , 按照内存布局顺序访问 , 将可以有效的利用 CPU Cache 带来的好处 , 这样我们代码的性能就会得到很大的提升 ,
如何提升指令缓存的命中率? 提升数据的缓存命中率的方式 , 是按照内存布局顺序访问 , 那针对指令的缓存该如何提升呢?
我们以一个例子来看看 , 有一个元素为 0 到 100 之间随机数字组成的一维数组:
本文插图
接下来 , 对这个数组做两个操作:
本文插图
- 第一个操作 , 循环遍历数组 , 把小于 50 的数组元素置为 0;
- 第二个操作 , 将数组排序;
本文插图
实际上 , CPU 自身的动态分支预测已经是比较准的了 , 所以只有当非常确信 CPU 预测的不准 , 且能够知道实际的概率情况时 , 才建议使用这两种宏 。如果提升多核 CPU 的缓存命中率? 在单核 CPU , 虽然只能执行一个进程 , 但是操作系统给每个进程分配了一个时间片 , 时间片用完了 , 就调度下一个进程 , 于是各个进程就按时间片交替地占用 CPU , 从宏观上看起来各个进程同时在执行 。而现代 CPU 都是多核心的 , 进程可能在不同 CPU 核心来回切换执行 , 这对 CPU Cache 不是有利的 , 虽然 L3 Cache 是多核心之间共享的 , 但是 L1 和 L2 Cache 都是每个核心独有的 , 如果一个进程在不同核心来回切换 , 各个核心的缓存命中率就会受到影响 , 相反如果进程都在同一个核心上执行 , 那么其数据的 L1 和 L2 Cache 的缓存命中率可以得到有效提高 , 缓存命中率高就意味着 CPU 可以减少访问 内存的频率 。当有多个同时执行「计算密集型」的线程 , 为了防止因为切换到不同的核心 , 而导致缓存命中率下降的问题 , 我们可以把线程绑定在某一个 CPU 核心上 , 这样性能可以得到非常可观的提升 。在 Linux 上提供了 sched_setaffinity 方法 , 来实现将线程绑定到某个 CPU 核心这一功能 。总结由于随着计算机技术的发展 , CPU 与 内存的访问速度相差越来越多 , 如今差距已经高达好几百倍了 , 所以 CPU 内部嵌入了 CPU Cache 组件 , 作为内存与 CPU 之间的缓存层 , CPU Cache 由于离 CPU 核心很近 , 所以访问速度也是非常快的 , 但由于所需材料成本比较高 , 它不像内存动辄几个 GB 大小 , 而是仅有几十 KB 到 MB 大小 。
推荐阅读
- 聚韬品牌策划公司|如何准备一个好的商业计划书,10分钟打动投资人?
- 芯片|热钱涌入引“虚火之忧” “中国芯”如何浴火新生
- 苹果手机|iPhone 12 mini拆解图揭示苹果是如何给设备瘦身的
- 数码|强迫症患者的幸福生活 篇十三:蜗居共享经济,如何彻底榨干你家里的电子设备
- 新全球化智库|中国企业如何到海外资本市场澳交所上市融资热点连接:中国企业如何到海外资本市场澳交所上市融资
- 富前程社群裂变|富船长:如何调研客户痛点?
- 银杏|满大街可见的银杏,怎么就比大熊猫还濒危?
- 科技互联热點|低迷大屏行业如何破局?荣耀智慧屏给出的答案是:品质!
- 陆超生财|想复制都难,移动支付体验全球第一的背后,支付宝做到了哪些扫码支付的基本原理。支付宝如何保障资金安全以及服务稳定为什么欧美发达国家
- |「晓霞走市场」私域运营标杆“老钟驾到”如何IP出圈?