JVM常见概念之条件移动

问题

当我们有分支频率数据时,有什么有趣的技巧可以做吗?什么是条件移动?

基础知识

如果您需要在来自一个分支的两个结果之间进行选择,那么您可以在 ISA 级别做两件不同的事情。

首先,你可以创建一个分支:

    # %r = (%rCond == 1) ? $v1 : $v2cmp %rCond, $1jne Amov %r, $v1jmp EA: mov %r, $v2E:

其次,您可以执行依赖于比较结果的预测指令 。在 x86 中,这采用条件移动 (CMOV) 的形式,当选定条件成立时执行操作:

# %r = (%rCond == 1) ? $v1 : $v2mov %r, $v1      ; put $v1 to %rcmp %rCond, ...cmovne %r, $v2   ; put $v2 to %r if condition is false

执行条件移动的优点是它有时会生成更紧凑的代码,就像在这个例子中一样,并且它不会受到可能的分支预测错误惩罚。缺点是它需要在选择返回哪一边之前计算两边,这可能会花费过多的 CPU 周期,增加寄存器压力等。在分支情况下,我们可以选择在检查条件后不计算内容。预测良好的分支将优于条件移动。

因此,是否执行条件移动的选择在很大程度上取决于其成本预测。这就是分支分析可以帮助我们的地方:它可以说出哪些分支可能没有被完美预测,因此适合 CMOV 替换。当然, 实际成本模型还包括我们正在处理的参数类型、两个计算分支的相对深度等。

实验

源码-用例1

@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class BranchFrequency {@Benchmarkpublic void fair() {doCall(true);doCall(false);}@CompilerControl(CompilerControl.Mode.DONT_INLINE)public int doCall(boolean condition) {if (condition) {return 1;} else {return 2;}}
}

执行结果

我们在每次调用时都会在分支之间进行切换,这意味着它的运行时配置文件在它们之间大约是 50%-50%。如果我们通过提供 -XX:ConditionalMoveLimit=0 来限制条件移动替换,那么我们就可以清楚地看到替换的发生。

# doCall, out of box variant4.36%  ...4ac: mov    $0x1,%r11d         ; move $1 -> %r113.24%  ...4b2: mov    $0x2,%eax          ; move $2 -> %res8.46%  ...4b7: test   %edx,%edx          ; test boolean0.02%  ...4b9: cmovne %r11d,%eax         ; if false, move %r11 -> %res7.88%  ...4bd: add    $0x10,%rsp         ; exit the method8.12%  ...4c1: pop    %rbp18.60%  ...4c2: cmp    0x340(%r15),%rsp...4c9: ja     ...4d00.14%  ...4cf: retq# doCall, CMOV conversion inhibited6.48%    ...cac: test   %edx,%edx         ; test boolean╭  ...cae: je     ...cc8│                                   ; if true...│  ...cb0: mov    $0x1,%eax         ; move $1 -> %res7.41% │↗ ...cb5: add    $0x10,%rsp        ; exit the method0.02% ││ ...cb9: pop    %rbp27.43% ││ ...cba: cmp    0x340(%r15),%rsp││ ...cc1: ja     ...ccf3.28% ││ ...cc7: retq││                                  ; if false...7.04% ↘│ ...cc8: mov    $0x2,%eax         ; move $2 -> %res0.02%  ╰ ...ccd: jmp    ...cb5            ; jump back

在此示例中,CMOV 版本的表现稍好一些:

Benchmark                              Mode  Cnt   Score    Error  Units# Branches
BranchFrequency.fair                   avgt   25   5.422 ±  0.026  ns/op
BranchFrequency.fair:L1-dcache-loads   avgt    5  12.078 ±  0.226   #/op
BranchFrequency.fair:L1-dcache-stores  avgt    5   5.037 ±  0.120   #/op
BranchFrequency.fair:branch-misses     avgt    5   0.001 ±  0.003   #/op
BranchFrequency.fair:branches          avgt    5  10.037 ±  0.216   #/op
BranchFrequency.fair:cycles            avgt    5  14.659 ±  0.285   #/op
BranchFrequency.fair:instructions      avgt    5  35.184 ±  0.559   #/op# CMOVs
BranchFrequency.fair                   avgt   25   4.799 ±  0.094  ns/op
BranchFrequency.fair:L1-dcache-loads   avgt    5  12.014 ±  0.329   #/op
BranchFrequency.fair:L1-dcache-stores  avgt    5   5.005 ±  0.167   #/op
BranchFrequency.fair:branch-misses     avgt    510⁻⁴            #/op
BranchFrequency.fair:branches          avgt    5   7.054 ±  0.118   #/op
BranchFrequency.fair:cycles            avgt    5  12.964 ±  1.451   #/op
BranchFrequency.fair:instructions      avgt    5  36.285 ±  0.713   #/op

您可能认为这是因为 CMOV 没有分支预测失误惩罚,但这种解释与计数器不一致。请注意,在两种情况下,“分支失误”几乎为零。这是因为硬件分支预测器实际上可以记住一个短暂的分支历史,而这种反复出现的分支对它们来说没有任何问题。性能差异的实际原因是分支情况下的跳跃:我们在关键路径上有一条额外的控制流指令。

源码-用例2

@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Fork(1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class AdjustableBranchFreq {@Param("50")int percent;boolean[] arr;@Setup(Level.Iteration)public void setup() {final int SIZE = 100_000;final int Q = 1_000_000;final int THRESH = percent * Q / 100;arr = new boolean[SIZE];ThreadLocalRandom current = ThreadLocalRandom.current();for (int c = 0; c < SIZE; c++) {arr[c] = current.nextInt(Q) < THRESH;}// Avoid uncommon traps on both branches.doCall(true);doCall(false);}@Benchmarkpublic void test() {for (boolean cond : arr) {doCall(cond);}}@CompilerControl(CompilerControl.Mode.DONT_INLINE)public int doCall(boolean condition) {if (condition) {return 1;} else {return 2;}}
}

执行结果

使用不同的 percent 值和 -prof perfnorm JMH 分析器运行它将产生以下结果:
在这里插入图片描述依据上图,你可以清楚地看到几件事:

  • 每个测试的分支数约为 5,而 CMOV 转换将其降至 4。这与之前的反汇编转储相关:我们将测试中的一个分支转换为 CMOV。另外 4 个分支来自测试基础设施本身。
  • 如果没有 CMOV,分支测试性能会受到影响,在 50% 的分支概率下会变得最差。这个峰值反映了硬件分支预测器几乎完全混乱,因为它每次操作都会遇到大约 0.5 次分支失误。这意味着分支预测器并不是一直猜错(这太荒谬了!),而只是一半的时间猜错。我推测基于历史的预测器会放弃,让静态预测器选择最近的分支,而我们只选择了一半的时间。
  • 使用 CMOV 后,我们可以看到操作时间几乎持平 。该图表明 CMOV 成本模型对于此测试来说可能过于保守,并且切换得有点晚。这并不一定意味着它有错误,因为其他情况的表现很可能会有所不同。尽管如此,当进行 CMOV 转换时,对分支情况的改进是巨大的。
  • 您可能会注意到,当分支预测准确率为 >97% 时,分支变体会低于 CMOV 中间平均值。当然,这又是测试、硬件、虚拟机特有的事情。

总结

分支分析允许在执行概率敏感指令选择时做出或多或少明智的选择。条件移动替换通常使用分支频率信息来驱动替换。这再次强调了使用与真实数据类似的数据来预热 JIT 编译代码的必要性,以便编译器能够针对特定情况进行有效优化。

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

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

相关文章

Debug-037-table列表勾选回显方案

效果展示&#xff1a; 图1 图2 最近实现一个支持勾选的el-table可以回显之前勾选项的功能。实现了一个“编辑”的功能&#xff1a; 在图1中的列表中有三行数据&#xff0c;当点击“更换设备”按钮时&#xff0c;打开抽屉显示el-table组件如图2所示&#xff0c;可以直接回显勾选…

Python散点图(Scatter Plot):数据探索的“第一张图表”

在数据可视化领域,散点图是一种强大而灵活的工具,它能够帮助我们直观地理解和探索数据集中变量之间的关系。本文将深入探讨散点图的核心原理、应用场景以及如何使用Python进行高效绘制。 后续几篇将介绍高级技巧、复杂应用场景。 Python散点图(Scatter Plot):高阶分析、散点…

docker利用ollama +Open WebGUI在本地搭建部署一套Deepseek-r1模型

系统&#xff1a;没有限制&#xff0c;可以运行docker就行 磁盘空间&#xff1a;至少预留50GB; 内存&#xff1a;8GB docker版本&#xff1a;4.38.0 桌面版 下载ollama镜像 由于docker镜像地址&#xff0c;网络不太稳定&#xff0c;建议科学上网的一台服务器拉取ollama镜像&am…

JavaScript |(六)DOM事件 | 尚硅谷JavaScript基础实战

学习来源&#xff1a;尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版 笔记来源&#xff1a;在这位大佬的基础上添加了一些东西&#xff0c;欢迎大家支持原创&#xff0c;大佬太棒了&#xff1a;JavaScript |&#xff08;六&#xff09;DOM事件 | 尚硅谷JavaScript基础…

卷积神经网络 - 梯度和反向传播算法

在卷积网络中&#xff0c;参数为卷积核中权重以及偏置。和全连接前馈网络类似&#xff0c;卷积网络也可以通过误差反向传播算法来进行参数学习。本文我们从数学角度&#xff0c;来学习卷积神经网络梯度的推导和其反向传播算法的原理。 一、梯度&#xff1a;损失函数 L 关于第 …

鸿蒙NEXT项目实战-百得知识库03

代码仓地址&#xff0c;大家记得点个star IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点&#xff1a; 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三…

【测试篇】关于allpairs实现正交测试用例保姆级讲解,以及常见的错误问题

前言 &#x1f31f;&#x1f31f;本期讲解关于测试工具相关知识介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话不多说…

OpenCV图像拼接(4)图像拼接模块的一个匹配器类cv::detail::BestOf2NearestRangeMatcher

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 cv::detail::BestOf2NearestRangeMatcher 是 OpenCV 库中用于图像拼接模块的一个匹配器类&#xff0c;专门用于寻找两幅图像之间的最佳特征点匹配…

C++: AVL树(实现旋转操作)

前言 map/set容器有个共同点是&#xff1a;其底层都是按照二叉搜索树来实现的&#xff0c;但是二叉搜索树有其自身的缺陷&#xff0c;假如往树中插入的元素有序或者接近有序&#xff0c;二叉搜索树就会退化成单支树&#xff0c;时间复杂度会退化成O(N)&#xff0c;因此map、set…

OpenCV中距离公式

一、各类距离公式总结 常见距离公式 欧氏距离&#xff1a; 曼哈顿距离&#xff08;L1&#xff09;‌&#xff1a; 切比雪夫距离&#xff08;Chessboard&#xff09;‌&#xff1a; 1、点与点距离(欧氏距离) ‌二维空间‌ 设两点坐标为 P1(x1,y1)、P2(x2,y2)&#xff0c;其距离…

六十天前端强化训练之第二十四天之Vue 模板语法与 v-for 指令大师级详解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、模板语法与指令知识精讲 1.1 模板语法三大核心 1.2 常见指令全家福 1.3 v-for 深度解析 二、商品列表示例完整实现 2.1 完整可运行代码 2.2 代码解析 2.3 运行效果…

XSS跨站脚本攻击漏洞(Cross Site Scripting)

前提概要 本文章主要用于分享XSS跨站脚本攻击漏洞基础学习&#xff0c;以下是对XSS跨站脚本攻击漏洞的一些个人解析&#xff0c;请大家结合参考其他文章中的相关信息进行归纳和补充。 XSS跨站脚本攻击漏洞描述 跨站脚本攻击&#xff08;XSS&#xff09;漏洞是一种常见且危害较…

用ArcGIS做一张符合环评要求的植被类型图

植被类型图是环境影响评价&#xff08;环评&#xff09;中的重要图件&#xff0c;需满足数据准确性、制图规范性和信息完整性等要求。本教程将基于ArcMap平台&#xff0c;从数据准备到成果输出&#xff0c;详细讲解如何制作符合环评技术规范的植被类型图。 ArcGIS遥感解译土地…

详解string类+迭代器

迭代器 概念&#xff1a;在 C 中&#xff0c;迭代器是访问容器&#xff08;如数组、列表、向量、字符串等&#xff09;元素的一种方式。迭代器提供了一种统一的接口&#xff0c;使得你可以使用相同的代码来遍历不同类型的容器。迭代器本质上是一个指针或者指针的封装&#xff0…

Sqoop安装部署

Apache Sqoop 简介 Sqoop&#xff08;SQL-to-Hadoop&#xff09;是 Apache 开源项目&#xff0c;主要用于&#xff1a; 将关系型数据库中的数据导入 Hadoop 分布式文件系统&#xff08;HDFS&#xff09;或相关组件&#xff08;如 Hive、HBase&#xff09;。 将 Hadoop 处理后…

软件工程之软件验证计划Software Verification Plan

个人主页&#xff1a;云纳星辰怀自在 座右铭&#xff1a;“所谓坚持&#xff0c;就是觉得还有希望&#xff01;” 本文为基于ISO26262软件验证计划模板&#xff0c;仅供参考。 软件验证计划&#xff0c;包括&#xff1a; 1. 软件需求验证计划 2. 软件架构设计验证计划 3. 软件单…

Windows系统本地部署OpenManus对接Ollama调用本地AI大模型

文章目录 前言1. 环境准备1.1 安装Python1.2. 安装conda 2. 本地部署OpenManus2.1 创建一个新conda环境2.2 克隆存储库2.3 安装依赖环境 3. 安装Ollama4. 安装QwQ 32B模型5. 修改OpenManus配置文件6. 运行OpenManus7.通过网页使用OpenManus8. 安装内网穿透8.1 配置随机公网地址…

计算机网络总结

一、IP地址及子网掩码、MAC 二、DNS、ARP 三、DHCP、UDP、TCP 四、NAT、NAPT、端口、网关 五、路由器与交换机 六、OSI模型 一、IP地址及子网掩码、MAC 1.1 IP地址的作用 用来全局网络通信&#xff08;门牌号&#xff09;用来区分相同网络之间的主机 1.2 子网掩码的作用 …

MySQL0基础学习记录-下载与安装

下载 下载地址&#xff1a; &#xff08;Windows&#xff09;https://dev.mysql.com/downloads/file/?id536787 安装 直接点next&#xff0c;出现&#xff1a; 点execute 然后一直next到这页&#xff1a; next 然后需要给root设置一个密码&#xff1a; 在next。。很多页…

React基础语法速览

一、项目创建 npm create vite 这里选择react即可&#xff0c;如图&#xff1a; 二、基本文件说明 react函数式编程时&#xff0c;用的是JSX语法进行开发的&#xff0c;这里注意&#xff0c;return时只能有一个根标签&#xff1b; 三、React核心语法 1.插值功能 插值可以使用…