为什么执行指针追踪时该跳转指令的开销如此之大?

2024-01-28

我有一个程序可以执行指针追逐 https://en.wikichip.org/wiki/pointer_chasing我正在尝试尽可能优化指针追逐循环。 我注意到perf record检测到函数中约 20% 的执行时间myFunction()用于执行跳转指令(用于在读取特定值后退出循环)。

需要注意的一些事项:

  • 指针追踪路径可以轻松地放入 L1 数据缓存中
  • using __builtin_expect避免分支错误预测的成本没有明显效果

perf record有以下输出:

Samples: 153K of event 'cycles', 10000 Hz, Event count (approx.): 35559166926                                                                                                                                                               
myFunction  /tmp/foobar [Percent: local hits]                                                                                                                                                                            
Percent│      endbr64                                                                                                                                                                                                                       
      ...
 80.09 │20:   mov     (%rdx,%rbx,1),%ebx                                                                                                                                                                                                    
  0.07 │      add     $0x1,%rax                                                                                                                                                                                                             
       │      cmp     $0xffffffff,%ebx                                                                                                                                                                                                      
 19.84 │    ↑ jne     20                                                                                                                                                                                                                    
      ...

我预计此循环中花费的大部分周期都用于从内存中读取值,这已由 perf 确认。 我还希望剩余的周期能够均匀地执行循环中的剩余指令。相反,perf 报告剩余周期的大部分用于执行跳转。

我怀疑通过了解用于执行这些指令的微操作可以更好地理解这些成本,但我有点不知道从哪里开始。


请记住,cycles事件必须选择一条指令来归咎,即使两者都mov-加载和宏融合cmp-and-branch uops 正在等待结果。这不是运行时一个或另一个“成本周期”的问题;而是一个问题。他们都在并行等待. (现代微处理器 90 分钟指南! http://www.lighterra.com/papers/modernmicroprocessors/ and https://agner.org/optimize/ https://agner.org/optimize/)

但是当“cycles”事件计数器溢出时,它必须选择一条特定的指令来“责备”,因为您使用的是统计抽样。这就是具有数百个正在运行的微指令的 CPU 必须发明不准确的现实图景的地方。通常,等待缓慢输入的那个会受到指责,我认为因为它通常是 ROB 或 RS 中最旧的,并且阻止前端分配新的微指令。

到底选择哪条指令的细节可能会告诉我们有关 CPU 内部结构的一些信息,但只是非常间接的。也许与它如何退休 4(?) 个 uop 组有关,而这个循环有 3 个 uop,所以当发生 perf 事件异常时哪个 uop 是最旧的。

出于某种原因,4:1 分割可能很重要,可能是因为采用非简单寻址模式的负载的 4+1 = 5 个周期延迟。 (我假设这是一个 Intel Sandybridge 系列 CPU,也许是 Skylake 衍生的?)就像,如果数据在与 perf 事件溢出(并选择采样)相同的周期从缓存到达,则mov不会受到指责,因为它实际上可以执行并摆脱困境?

IIRC、BeeOnRope 或其他人通过实验发现 Skylake CPU 倾向于在异常到达后让最旧的未退休指令退休,至少如果不是缓存未命中的话。在你的情况下,那就是cmp/jne位于循环的底部,按程序顺序出现在下一次迭代顶部的加载之前。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么执行指针追踪时该跳转指令的开销如此之大? 的相关文章

  • X86 汇编将小写字母转换为大写字母

    实现toUpper函数 将字符串中的小写字母转换 为大写 该函数采用一个参数 char string 字符串是一个 char类型指针 指向字符串的开头 因为C 样式字符串以零结尾 我们不需要取长度 字符串作为另一个参数 我需要帮助开始 我不
  • 如何创建一个扩展为“(x+y*240)*2”这样的表达式的 GNU GAS 宏?

    我正在使用 GAS 为 ARM Linux 构建一个程序 但我想做一些宏以使我的开发更加智能 然后我想知道 我怎样才能为此做一个宏 x y 240 2 were x and y are int 将像这样使用 mov r0 MACRO SHO
  • 如何使用 python 子进程杀死性能记录?

    我正在尝试使用性能实用程序 https www brendangregg com perf html监视我的系统 它将在 python 脚本中启动和终止 我创建了一个沙箱 如下所示 extra params F 99 g a record
  • c++11 中指针的“auto”类型赋值是否需要“*”?

    鉴于我的变量是指针 如果我将其分配给 auto 类型的变量 我是否指定 std vector
  • 删除指针后将其设为 NULL 是一个好习惯吗?

    我首先要说的是 使用智能指针 您将永远不必担心这个问题 下面的代码有什么问题 Foo p new Foo use p delete p p NULL 这是由答案和评论 https stackoverflow com questions 19
  • 段错误...关于你好世界

    这段代码非常简单 但我在 x86 64 Linux 系统上遇到了段错误 这让我很烦恼 刚开始接触asm 请耐心等待 与 NASM 组装nasm f elf64 test asm 与连接ld o test test o SECTION tex
  • 用泛型类型替换模板化函数指针

    我写了以下包装std bind and std queue include Queue h template
  • 当我尝试在 Armv8 程序集中分配数组时,执行冻结

    所以我正在用汇编语言进行编程 这只是一个简单的代码 这样我就可以学习如何分配数组 以便稍后在 NEON 编程中使用它们 ASM FUNC FPE data balign 8 array skip 80 array1 word 10 20 3
  • 将结构化数据类型从 Fortran 传递到 C++ [重复]

    这个问题在这里已经有答案了 我在 Fortran 中有一个结构化类型 其中包含大量数据 包括指针 real 8 指针数据类型 我正在为某些 Fortran 例程开发 C API 我需要在对 Fortran 例程的调用之间保留该结构的内容 我
  • 函数名前的星号有什么作用?

    我对在大多数具有我不熟悉的函数声明的 C 程序中看到的内容感到困惑 void func name void param 什么是 暗示该功能 我的理解 在变量类型中的特点是它创建一个指向另一个变量的指针 因此它可以跟踪后一个变量存储在内存中的
  • 段寄存器如何参与内存地址转换?

    到目前为止我所学到的有关细分的知识 虚拟地址包含段选择器和偏移量 段选择器与GDTR配合使用 查找段描述符的线性地址 段描述符保存有关所选段的信息 包括其线性地址 所以 我的问题是 根据我所读到的内容 虚拟地址被加载到段寄存器中 然后以某种
  • _addcarry_u64 和 _addcarryx_u64 与 MSVC 和 ICC

    MSVC 和 ICC 都支持内在函数 addcarry u64 and addcarryx u64 根据英特尔的内在指南 https software intel com sites landingpage IntrinsicsGuide
  • 指向基类的成员指针

    全部 我不明白为什么下面的代码需要强制转换才能工作 有人可以解释一下吗 class Base class Derived public Base class Class public Derived member Derived obj B
  • 无法将新地址分配给函数中的指针? [复制]

    这个问题在这里已经有答案了 不久前 我有一个编程作业 偶然发现了这个小问题 当我给一个函数一个指针作为参数时 我无法更改它指向的地址 我通过返回我想要指针指向的新地址解决了这个问题 但我仍然想知道为什么不可能操作指针参数 因为所有内存分配函
  • Fortran 指针数组

    同样 Fortran 中的指针数组 好吧 我有一个派生类型 type t context pointer type t context pointer p ctx end type t context pointer 当我在主程序中执行以下
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l
  • 从 64 位 nasm 代码接收 32 位寄存器

    我正在学习 64 位 nasm 我通过执行以下操作来汇编 nasm 文件 该文件仅包含 64 位寄存器 nasm f elf64 HelloWorld nasm o HelloWorld o 并链接它执行以下操作 ld HelloWorld
  • 将 1 字节立即值添加到 2 字节内存位置

    The add说明文档来 自这一页 http x86 renejeschke de html file module x86 id 5 html说如下 请注意我突出显示的两条说明 我在 NASM 中尝试了以下代码 符合第一个突出显示的指令
  • reinterpret_cast 为 void* 是否合法

    我在看https en cppreference com w cpp language reinterpret cast https en cppreference com w cpp language reinterpret cast我注

随机推荐

  • 服务重启后 Docker 节点宕机

    我的服务器似乎空间不足 并且某些已部署的 Docker 堆栈出现了一些问题 我花了一段时间才弄清楚 但最终我做到了 并删除了一些容器和图像以释放一些空间 我能够跑service docker restart它起作用了 然而 也存在一些问题
  • 通过java应用程序发送附有excel文件的电子邮件 - 不起作用

    我试图通过Java应用程序发送一封邮件 其中包含excel文件作为附件 而不实际创建该文件 excel文件中的数据来自数据库 我可以发送带有附件的邮件 但文件是文本 制表符分隔 格式 但我希望该文件仅为 Excel 格式 请帮忙 以下是代码
  • 在 Java 调试器中,如何忽略从未通过我的代码的异常

    我目前正在使用 IntelliJ IDEA 进行 Java 开发 但我也对针对其他 IDE 的答案或调试 Java 代码的一般概念感兴趣 因为我在许多 IDE 中都错过了这个功能 所以我不确定在从其他语言转移我的调试习惯时是否错过了工作流程
  • Google Dataflow(Apache Beam)JdbcIO批量插入mysql数据库

    我正在使用 Dataflow SDK 2 X Java API Apache Beam SDK 将数据写入 mysql 我创建了基于管道Apache Beam SDK 文档 https beam apache org documentati
  • 使用 window.open() 的多个窗口

    众所周知 如果您单击嵌入其中的提交按钮onClick windown open 这将打开一个新窗口 其中包含您指定的所有可爱属性 但是 如果继续单击父窗口并再次单击 提交 按钮而不关闭先前的弹出窗口 则同一窗口将被新数据覆盖 现在我需要一种
  • 词汇量和嵌入维度之间的首选比例是多少?

    例如使用时gensim word2vec或用于训练嵌入向量的类似方法我想知道什么是好的比率 或者嵌入维度与词汇量之间是否有首选比率 随着更多数据的出现 这种情况会如何变化 由于我仍在讨论这个主题 因此在训练嵌入向量时如何选择合适的窗口大小
  • 哪些 OpenGL ES 2.0 纹理格式可进行颜色、深度或模板渲染?

    From OpenGL ES 2 0 规范 http www khronos org registry gles specs 2 0 es full spec 2 0 25 pdf第 4 4 5 节 表 4 5 中未列出的格式 包括压缩的内
  • 如何将两个日期列表合并为一系列日期间隔?

    我有开始日期列表和结束日期列表 他们已经排序了 start dates datetime date 2009 11 5 datetime date 2009 11 13 datetime date 2009 11 25 datetime d
  • 实体框架:如何在提交之前检查值是否存在

    我正在使用存储库模式 我有一个国家 地区存储库 我正在使用服务来提交该存储库 我应该在哪里检查该国家 地区是否已存在于数据库中 我会抛出异常吗 有没有一种方法可以在一次数据库调用中做到这一点 如果不存在则检查并插入 如果可以的话 可以在服务
  • 使用区域设置来检测是否使用英制单位

    我正在开发一个应用程序 想要以厘米 cm 或英寸 为单位显示长度 有没有办法从区域设置中选择正确的单位 无论如何 我还将输入一个选项 以便用户可以覆盖区域设置 美国 利比里亚和缅甸应使用英制单位 而世界其他国家应使用正常单位 一种方法是将此
  • 将 CSV 转换为 RDF,其中一列是一组值

    我想将 CSV 转换为 RDF 事实上 该 CSV 的一列是一组用分隔符 在我的例子中为空格符 连接的值 以下是 CSV 示例 带标题 col1 col2 col3 A B C D John M X Y Z Jack 我希望转换过程创建一个
  • 使用T4模板基于POCO生成多个类

    当我向数据库添加表时 我正在寻找一种提高工作效率的方法 一般来说 当我添加新表时 我必须执行以下步骤 将表添加到数据库 简单 创建相应的 EF Code First 类 我不使用数据库迁移 创建一个与 2 中创建的 EF 类匹配的 POCO
  • 需要帮助了解 Firebase Storage CDN

    我正在构建一个有声读物应用程序 并将音频文件上传到 Firebase 存储上 我的问题是我在旧金山和多伦多经历了不同的表现 我的印象是 Firebase Storage 具有内置 CDN 如果是这样 我需要在某处启用它吗 如果没有 如何将
  • Breeze:EFContextProvider/Breeze 控制器和服务层

    使用 Breeze 时 我想知道如何将其与处理电子邮件通知 审核日志 业务验证 即客户必须存在 等事务的服务层集成 例如 假设有以下场景 public class SalesAppRepository private readonly EF
  • 单个 APN 是一个组织中多个应用程序的关键

    我的组织维护多个应用程序 并且对于如何使用 APN 密钥存在困惑 我们正在使用 firebase 发送推送通知 So far we have two apple keys for two different applications But
  • 到 .accdb 文件的 ODBC 连接

    我正在尝试从我一直在处理的统一项目中访问 Microsoft Access 数据库文件 但它不断抛出异常 因为它无法找到该文件并且没有选择标准河流 代码 using UnityEngine using UnityEngine UI usin
  • DynamoDB 预配的写入容量单位经常意外超出

    我相信我了解写入 读取容量单位 它们的工作原理以及在 DynamoDB 中的计算方式 证明就是我明白this https linuxacademy com howtoguides posts show topic 20310 how to
  • 从 Clojure Repl 和 Leiningen 运行测试

    作为 clojure 的新手 我使用 leiningen 创建了一个示例项目 lein new app first project 这给了我这个目录 doc intro md LICENSE project clj README md re
  • Android 将 Drawable 和 Shape 合并为一个 Drawable(以编程方式)

    我正在设置android drawable单选按钮的编程方式如下 Drawable unchecked getResources getDrawable R drawable ic room car Drawable d getResour
  • 为什么执行指针追踪时该跳转指令的开销如此之大?

    我有一个程序可以执行指针追逐 https en wikichip org wiki pointer chasing我正在尝试尽可能优化指针追逐循环 我注意到perf record检测到函数中约 20 的执行时间myFunction 用于执行