CPU性能优化--前端优化

news/2024/12/23 7:19:48/

绝大部分时候,CPU前端低效可以描述为这样一种情况,后端在等待指令来执行,但是前端不能给后端提供指令。结果就是,没有做任何有意义的工作,CPU时钟周期被浪费了。因为现代处理器是4发射的,所以会有这样一种情况,即4个可用的槽位没有被填满,这也是低效执行的一个原因。实际上,IDQ_UOPS_NOT_DELIVERED性能事件会统计有多少可用的槽位因为前端停顿二没有被利用。TMA使用该性能事件的值来就按它的前端绑定指标。

前端不能被执行单元提供指令的原因有很多,不过通常被归结于缓存利用率和无法从内存中获取指令两类。建议只有当TMA显示较高的 前端绑定 指标时,才开始考虑针对CPU前端的代码优化。

7.1 机器码布局

当编译器将源代码翻译为机器码时,会生成一个串行的字节序列,例如,对于下面的代码。

if (a <= b)

c = 1

编译器会生成如下的汇编代码

cmp rax, rdx

jg .label

汇编指令会被解码,并如下布局在内存中

cmp rax, rdx

jg 40051s

mov rcx, 1

这就是所谓的机器码布局注意同一个程序可能会不同方式布局给定两个函数foobar我们可以二进制文件中放置bar然后再放foo, 也可以相反顺序放置影响指令内存放置位置偏移量也会反击来影响生成二进制文件性能

7.2 基本块

基本块只有一个入口一个出口指令序列40展示一个基本示例其中MOV指令入口JA指令出口虽然基本块可以多个前导后继但是基本块中间没有任何指令可以跳出基本块

7.3 基本块布局

假设程序中有一个热点路径

if (cond)

coldFunc()

41展示了这段代码两种可能物理布局41a展示没有任何提示提供情况下绝大部分编译器默认产生布局41展示如果我们反转判断条件cond热点代码放在直通位置产生布局

一般情况下哪个布局更好通常依赖cond真的还是假的如果cond通常那么最好的选择默认布局因为另一个布局需要做两次而不是一次跳转动作此外一般情况下我们会想cond判断条件里面函数然而在这个例子中我们知道coldFUnc 是一个错误处理函数并且不太可能会被经常执行通过选择41b布局我们保持了热点代码直通并且分支转换未被选取分支

对于前面展示代码41展示布局表现更好原因有几个首先从本质未被选取分支选取耗时更少一般情况下现代Intel CPU每个时钟周期可以执行两个未被选取分支但是两个时钟周期才能执行一个选取分支

热路径检查条件

调用coldFunc 可能会被內联

路径

热路径检查条件

热路径

调用coldFunc 可能会被內联

其次41布局可以更充分利用指令微操作缓存DSB因为所有热点代码都是连续所以没有缓存碎片问题L1指令缓存所有缓存行都会被热点代码使用微操作缓存也是一样因为也是基于代码布局进行缓存

最后被选取分支对于读取单元来说更耗时读取单元16字节=连续单位进行读取所以每个被选取跳转指令都意味着跳转之后所有字节都是无用这会降低最大有效读取吞吐量

为了编译器提供参考意见产生优化版本机器码布局开发者可以使用

__builtin_expect 提示编译器

if (__builtin_expect(cond, 0))

coldFunc();

开发者通常会使用LIKELY 帮助定义代码更具有可读性所以你会发现下面代码普遍

if (LIKELY(ptr != nullptr))

7.4 基本块对齐

有时候性能由于指令内存布局偏移而发生明显变化我们一起研究代码清单16简单函数

void benchmark_func(int* a)

{

for (int i = 0; i< 32; ++i)

a[i] += 1;

}

合格的优化编译器可能会Skylake架构生成如下机器码

_Z4benchmark_funcPi

mov rax, 0xffffffff80

vpcmpeqd ymm0, ymm0, ymm0

nop DWORD PTR [rax + rax * 1 + 0x0]

vmovdqu ymm1, YMMWORD PTR [rdi + rax * 1 + 0x80]

vpsubd ymm1, ymm1, ymm1

vmovdqu YMMWORD PTR [rdi + rax * 1 + 0x80], ymm1

add rax, 0x20

jne 4046b0

vzeroupper

ret

代码本身Skylake架构来说很合理的但是布局并不完美循环对应指令标出数据缓存相同指令缓存通常也是64字节42粗线框表示缓存行边界注意循环跨越了多条缓存行缓存行0x80 - 0xbf缓存行0xc0 - 0xff结束这种情况通常导致CPU前端出现性能问题尤其上面讲到小循环

为解决该问题,我们可以使用NOP指令将循环指令向前移动16个字节,以便让整个循环驻留在一条缓存行中。图42b中用深色阴影区的NOP指令展示这样做的效果,注意,由于基准测试值运行了热点循环,因此可以确定两个缓存行都会驻留在L1指令缓存中,图42b中布局性能更好的原因并不容易解释清楚,涉及相当多的微架构内容,我们本书中不会讨论这些细节

尽管CPU架构师努力在设计中隐藏这种瓶颈,但是仍然存在类似的代码布局对性能产生影响的情况。

默认情况下,LLVM编译器识别循环并且按照16字节边界对齐他们。可以使用-mllvm-align-all-blocks编译选项,然而,该选项使用要小心,可能导致性能劣化,插入会被执行到的NOP指令,增加程序开销,尤其当它们在关键路径上时,NOP指令不需要被执行,但是,他们仍然需要被从内存读取,解码和退休。类似所有其他指令,后者会额外消耗前端数据结构和用于记账的缓冲区空间。

为了细粒度的控制对齐,还可以使用ALIGN汇编指令,针对实验场景,开发人员可以先生成汇编列表,然后插入ALIGN指令

.loop

dec rdi

jnz rdi

7.5 函数拆分

思想时把热点代码和冷代码分开,优化对在热点路径中具有复杂CFG和大量冷代码并且相对较大的函数时有益的。代码清单17中展示了该转换可能有收益的样例代码,为了从热路径中移除冷基本块,我们可以把它截取出来并放到一个新的函数中,并调用这个新的函数。


http://www.ppmy.cn/news/1557404.html

相关文章

【漏洞复现】CVE-2023-37461 Arbitrary File Writing

漏洞信息 NVD - cve-2023-37461 Metersphere is an opensource testing framework. Files uploaded to Metersphere may define a belongType value with a relative path like ../../../../ which may cause metersphere to attempt to overwrite an existing file in the d…

微信小程序实现画板画布自由绘制、选择画笔粗细及颜色、记录撤回、画板板擦、清空、写字板、导出绘图、canvas,开箱即用

目录 画板创建canvas绘制及渲染画笔粗细功能实现画笔颜色选择画笔痕迹撤回、板擦、画布清空canvas解析微信小程序中 canvas 的应用场景canvas 与 2D 上下文、webgl 上下文的关系图像的加载与绘制说明代码说明画板创建 canvas绘制及渲染 在wxml添加对应的canvas标签代码,并在j…

分布式协同 - 分布式事务_TCC解决方案

文章目录 导图Pre流程图2PC VS 3PC VS TCC2PC&#xff08;Two-Phase Commit&#xff0c;二阶段提交&#xff09;3PC&#xff08;Three-Phase Commit&#xff0c;三阶段提交&#xff09;TCC&#xff08;Try-Confirm-Cancel&#xff09;2PC、3PC与TCC的区别2PC、3PC与TCC的联系 导…

函数:参数与返回值类型

本文我们将深入探讨 函数的参数和返回值类型&#xff0c;这是 TypeScript 中最常用的特性之一。了解如何为函数参数和返回值添加类型&#xff0c;不仅能帮助你避免常见的错误&#xff0c;还能提高代码的可读性和可维护性。 在 JavaScript 中&#xff0c;函数的参数和返回值是没…

2024年智能船舶与机电系统

重要信息 会议官网&#xff1a;www.icises.org 会议时间&#xff1a;2024年12月27-29日 会议地点&#xff1a;中国广州 大会 2024年智能船舶与机电系统&#xff08;ICISES 2024&#xff09;初定于2024年12月27-29日在中国广州举行。会议主要围智能船舶与机电系统等研究领域…

RF分类-随机森林(Random Forest)

RF分类详细介绍 源码 什么是RF分类&#xff1f; RF分类&#xff08;随机森林分类&#xff09;是一种集成学习方法&#xff0c;基于**随机森林&#xff08;Random Forest&#xff09;**算法&#xff0c;用于解决分类和回归问题。随机森林通过构建多个决策树并结合它们的预测结…

渗透测试-前后端加密分析之RSA+AES

本文是高级前端加解密与验签实战的第8篇文章&#xff0c;本系列文章实验靶场为Yakit里自带的Vulinbox靶场&#xff0c;本文讲述的是绕过RSA与AES加密来爆破登录。 由于RSA加解密有长度限制&#xff0c;以及解密速度等问题&#xff0c;所以如https等协议都是用非对称加密对称加…

python rabbitmq实现简单/持久/广播/组播/topic/rpc消息异步发送可配置Django

windows首先安装rabbitmq 点击参考安装 1、环境介绍 Python 3.10.16 其他通过pip安装的版本(Django、pika、celery这几个必须要有最好版本一致) amqp 5.3.1 asgiref 3.8.1 async-timeout 5.0.1 billiard 4.2.1 celery 5.4.0 …