rdpmc:令人惊讶的行为

2023-12-22

我试图理解 rdpmc 指令。因此我有以下 asm 代码:

segment .text
global _start

_start:
    xor eax, eax
    mov ebx, 10
.loop:
    dec ebx
    jnz .loop

    mov ecx, 1<<30
    ; calling rdpmc with ecx = (1<<30) gives number of retired instructions
    rdpmc
    ; but only if you do a bizarre incantation: (Why u do dis Intel?)
    shl rdx, 32
    or  rax, rdx

    mov rdi, rax ; return number of instructions retired.
    mov eax, 60
    syscall

(该实现是翻译rdpmc_指令() https://software.intel.com/en-us/forums/software-tuning-performance-optimization-platform-monitoring/topic/595214.) 我认为这段代码应该在命中之前执行 2*ebx+3 条指令rdpmc指令,所以我期望(在这种情况下)我应该得到 23 的返回状态。

如果我跑perf stat -e instruction:u ./a.out在这个二进制文件上,perf告诉我我已经执行了 30 条指令,这看起来是正确的。但如果我执行二进制文件,我得到的返回状态为 58 或 0,不是确定性的。

我在这里做错了什么?


固定计数器不会一直计数,只有当软件启用它们时才计数。通常(内核侧)perf执行此操作,并在启动程序之前将它们重置为零。

固定计数器(如可编程计数器)具有控制是否 它们计入用户、内核或用户+内核(即始终)。我假设Linux的perf当没有任何东西使用它们时,内核代码将它们设置为不计数。

如果您想自己使用原始 RDPMC,则需要对计数器进行编程/启用(通过设置IA32_PERF_GLOBAL_CTRL and IA32_FIXED_CTR_CTRLMSRs),或者通过仍然在下面运行你的程序来让 perf 为你做这件事perf. e.g. perf stat ./a.out

如果你使用perf stat -e instructions:u ./perf ; echo $?,固定计数器实际上会在输入代码之前归零,因此您可以通过使用获得一致的结果rdpmc一次。否则,例如使用默认的-e instructions(不是:u)你不知道计数器的初始值。您可以通过获取增量来解决这个问题,在开始时读取一次计数器,然后在循环之后读取一次。

退出状态只有 8 位宽,所以这个小技巧可以避免 printf 或write()仅适用于非常小的计数。

这也意味着构建完整的 64 位是没有意义的rdpmc结果:输入的高 32 位不影响 a 的低 8 位sub结果是因为进位仅从低位传播到高位。一般来说,除非您期望计数 > 2^32,否则只需使用 EAX 结果。即使原始 64 位计数器在您测量的时间间隔内回绕,您的减法结果仍然是 32 位寄存器中的正确小整数。


比你的问题还要简化。另请注意缩进操作数,以便即使助记符长度超过 3 个字母,它们也可以保持在一致的列中。

segment .text
global _start

_start:
    mov   ecx, 1<<30      ; fixed counter: instructions
    rdpmc
    mov   edi, eax        ; start

    mov   edx, 10
.loop:
    dec   edx
    jnz   .loop

    rdpmc               ; ecx = same counter as before

    sub   eax, edi       ; end - start

    mov   edi, eax
    mov   eax, 231
    syscall             ; sys_exit_group(rdpmc).  sys_exit isn't wrong, but glibc uses exit_group.

在下面运行这个perf stat ./a.out or perf stat -e instructions:u ./a.out,我们总是得到23 from echo $? (instructions:u显示30,比该程序实际运行的指令数多了1,包括syscall)

23 条指令正好是第一条指令之后的指令数rdpmc,但包括第二个rdpmc.

如果我们注释掉第一个rdpmc并在下面运行它perf stat -e instructions:u,我们不断得到26作为退出状态,并且29 from perf. rdpmc是要执行的第24条指令。 (RAX 开始时初始化为零,因为这是一个 Linux 静态可执行文件,因此动态链接器之前没有运行_start)。我想知道是否sysret在内核中被视为“用户”指令。

但随着第一个rdpmc注释掉,运行在perf stat -e instructions(不是:u)给出任意值,因为计数器的起始值不固定。所以我们只是将(某个任意起点 + 26)mod 256 作为退出状态。

但请注意,RDPMC 是not序列化指令,并且可以乱序执行。一般来说你可能需要lfence,或者(正如 John McCalpin 在您链接的线程中建议的那样)给 ECX 一个对您关心的指令结果的错误依赖。例如and ecx, 0 / or ecx, 1<<30有效,因为与异或归零不同,and ecx,0不打破依赖性。

这个程序中没有发生任何奇怪的事情,因为前端是唯一的瓶颈,所以所有指令基本上一发出就执行。另外,rdpmc就在循环之后,因此循环退出分支的分支错误预测可能会阻止它在循环结束之前发送到 OoO 后端。


面向未来读者的 PS:在 Linux 上启用用户空间 RDPMC 的一种方法,无需任何自定义模块perf需要记录在perf_event_open(2) http://man7.org/linux/man-pages/man2/perf_event_open.2.html:

echo 2 | sudo tee /sys/devices/cpu/rdpmc    # enable RDPMC always, not just when a perf event is open
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

rdpmc:令人惊讶的行为 的相关文章

  • 有效地生成所有排列

    我需要尽快生成所有排列 https en wikipedia org wiki Permutation整数的0 1 2 n 1并得到结果作为NumPy https numpy org 形状数组 factorial n n 或者迭代此类数组的
  • 设置 IRQ 映射

    我正在遵循一些教程和参考文献来尝试设置我的内核 我在教程中遇到了一些不熟悉的代码 但根本没有解释它 这是我被告知映射的代码16 IRQs 0 15 到 ISR 地点32 47 void irq remap void outportb 0x2
  • 为什么用scala写的代码比用java写的慢6倍?

    我不确定我在编写 scala 代码时是否犯了一些错误 问题是 The four adjacent digits in the 1000 digit number that have the greatest product are 9 9
  • C# 中单个 & 符号的第二个含义是什么?

    我在 C 中使用了单个与号 来表示 检查second条件语句即使第一个是false 但以下似乎是不同的意思 of 总而言之 谁能解释一下如何i 1在下面的例子中有效吗 List
  • SQL Server 不使用索引将日期时间与非空进行比较

    我有一个与其他任何表都不相关的简单表 它有一个非 PK 列 它是一个日期 我已经为该列创建了一个非聚集索引 如果我提出这个查询 select from table where datecolumn is not null 但如果我删除 no
  • 为什么 FMA _mm256_fmadd_pd() 内在函数有 3 个 asm 助记符:“vfmadd132pd”、“231”和“213”?

    有人可以向我解释一下为什么融合乘法累加指令有 3 种变体 vfmadd132pd vfmadd231pd and vfmadd213pd 而只有一个 C 内在函数 mm256 fmadd pd 为了简单起见 在 AT T 语法中 有什么区别
  • 为什么 System.nanoTime() 比 System.currentTimeMillis() 慢(性能)?

    今天我做了一个快速基准测试来测试速度性能System nanoTime and System currentTimeMillis long startTime System nanoTime for int i 0 i lt 1000000
  • jQuery - 提高处理 XML 时的选择器性能

    我正在处理一个 XML 文件 当使用 XPath 样式选择器选择节点时 该文件的性能非常慢 这是运行特别慢的部分代码 for i 0 i
  • Python——捕获异常的效率[重复]

    这个问题在这里已经有答案了 可能的重复 Python 常见问题解答 异常有多快 https stackoverflow com questions 8107695 python faq how fast are exceptions 我记得
  • iPhone 3GS 上的 ARM 与 Thumb 性能比较,非浮点代码

    我想知道是否有人有关于 iPhone 3GS 上 ARM 与 Thumb 代码性能的硬性数据 特别是对于非浮点 VFP 或 NEON 代码 我知道 Thumb 模式下的浮点性能问题 更大的 ARM 指令的额外代码大小是否会在某个时刻成为性能
  • GCC的sqrt()编译后如何工作?使用哪种root方法?牛顿-拉夫森?

    只是对标准感到好奇sqrt 来自 GCC 上的 math h 我自己编码的sqrt 使用牛顿拉夫森来做到这一点 是的 我知道 fsqrt 但CPU是如何做到这一点的呢 我无法调试硬件 现代 CPU 中的典型 div sqrt 硬件使用 2
  • 页面上首次调用 Url.Action 速度很慢

    我有一个相当简单的 ASP MVC 视图的性能问题 这是一个登录页面 应该几乎是即时的 但需要大约半秒钟 经过大量挖掘后 问题似乎出在第一个调用上Url Action 大约需要 450 毫秒 根据迷你分析器 http miniprofile
  • Android 性能:SharedPreferences 的成本

    当我的应用程序启动时 我使用分片首选项中的值填充容器类 这个想法是处理 SharedPreferences 和 PreferenceManager 一次 因为我猜它们很重 这是一个示例 SharedPreferences prefs Pre
  • 当我使用可变参数而不是常量参数时,为什么我的内联表 UDF 慢得多?

    我有一个表值内联 UDF 我想过滤该 UDF 的结果以获得一个特定值 当我使用常量参数指定过滤器时 一切都很好 并且性能几乎是瞬时的 当我使用可变参数指定过滤器时 它会花费明显更大的时间块 大约是逻辑读取的 500 倍和持续时间的 20 倍
  • LC3 LEA指令和存储的值

    我对这个问题感到困惑 指令后寄存器0中存储的值是多少 LEA R0 A 被处决了吗 为什么答案是x370C 我认为应该将A的地址加载到R0中 如果是这样我们怎么知道地址 有人可以帮忙吗 非常感谢 ORIG X3700 LEA R0 A LD
  • IIS7 上的 ASP.NET 应用程序 - iisreset 后启动速度非常慢

    我有一个在 Windows 2008 上的 IIS7 下运行的 ASP NET 3 5 网站 当我重新启动 IIS iisreset 然后点击一个页面时 初始启动非常慢 我在 Process Explorer 中看到以下活动 w3wp ex
  • 红宝石接球和效率

    catch在 Ruby 中意味着跳出深度嵌套的代码 在 Java 中 例如用Java也可以达到同样的效果try catch用于处理异常 但它被认为是糟糕的解决方案 而且效率非常低 在 Ruby 中 我们有处理异常的方法begin raise
  • 32位PPC rlwinm指令

    我在理解上有点困难rlwinmPPC 汇编指令 旋转左字立即然后与掩码 我正在尝试反转函数的这一部分 rlwinm r3 r3 0 28 28 我已经知道什么了r3 is r3在本例中是一个 4 字节整数 但我不确定这条指令到底是什么rlw
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • python 日志记录会刷新每个日志吗?

    当我使用标准模块将日志写入文件时logging 每个日志会分别刷新到磁盘吗 例如 下面的代码会将日志刷新 10 次吗 logging basicConfig level logging DEBUG filename debug log fo

随机推荐

  • 具有相同名称的命名参数

    我正在使用 caret 库对某些树进行一些交叉验证 该库提供了一个函数 称为train 它接受一个命名参数 方法 通过省略号 它应该让其他参数传递给它调用的另一个函数 这个另一个函数 rpart 采用同名参数 方法 因此我想传递两个同名的参
  • 符号与数字数学 - 性能

    与数值计算相比 符号数学计算 尤其是求解非线性多项式系统 是否会导致巨大的性能 计算速度 劣势 有这方面的基准 数据吗 找到一个相关问题 符号计算与数值计算 https scicomp stackexchange com questions
  • 如何配置 Protractor 使用 Cucumber

    As of 0 20 1 http ng learn org 2014 03 Protractor 0 20 1 Protractor 现在完全支持 Cucumber 但我正在努力寻找有关如何正确配置它的任何文档 知道如何设置 world
  • Python获取焦点条目名称

    我试图在按下向上或向下箭头键时增加或减少输入值 为此 我需要首先找到焦点所在的条目 我正在尝试这样做 focus get 问题是我无法弄清楚它是如何工作的或者它返回什么 它为每个条目返回 1 个唯一的数字 类似于 45191744 但每次我
  • jsdom 和 $(document).ready

    我看起来就像当我浏览一页时jsdom the document ready页面脚本中的块没有被执行 这是 HTML If everything works you should see a message here h2 h2
  • 为不同版本的python升级pip

    我的计算机上安装了两个版本的 python 3 6 和 3 7 刚刚使用命令将 pip 升级到最新版本 19 0 1 python m pip install upgrade pip不过我认为它只升级了 python 3 6 版本的 pip
  • Windows 版 Git Bash 无法使用“lein repl”命令

    我实际上使用 git bash 而不是默认的 Windows 命令 shell cmd 但我无法在 git bash 中运行 lein repl 它没有显示任何内容 我必须按 ctrl c 才能重新获得控制权 有什么建议吗 谢谢 EDIT
  • 非类型模板参数和要求

    我正在学习概念 我无法找到一种方法来限制非类型模板参数的值 而不是类型 Example https godbolt org z d48Gv1编译的代码 尽管我希望它没有 由于要求失败 include
  • Python 中的 Parallel.For

    Python中有类似C 优秀的Parallel For的东西吗 我只想做一个计算 simu c for c in clusterSizes 在平行下 存档的最简单方法是什么 PS 我尝试了 joblib 但在我的情况下 它只是启动 启动和启
  • HTTP/1.1 415 不支持的媒体类型 Excel 文件 Dawnload 问题

    我在 silverlight 目录中有 Excel 导出功能 用户右键单击目录 这将触发通过浏览器的下载 public static void ExportValues CatalogData data var excelData new
  • 从 Javascript 获取 InDesign CS5 中的当前页码

    获取光标所在页面的 DOM 表达式是什么 app activeDocument currentPage 你要 app activeWindow activePage name 这将为您提供字符串形式的实际页码名称 即 如果您的页面以罗马数字
  • 如何为后台网格行添加自定义删除选项

    我已经使用开发了可编辑网格backgrid http backgridjs com 而且看起来也不错 以下是我的输出 当我选择复选框并单击delete图标 则所选行将被删除 现在我还想在每一行上都有删除选项 以便用户可以直接删除该行 如何在
  • 为什么函数“onaddstream”从未被调用?

    您好 我按照本教程创建了一个简单的 webrtc 示例 https www webrtc experiment com docs WebRTC PeerConnection html https www webrtc experiment
  • 在 JS Helper CakePHP 中手动触发事件

    我陷入了困境 我正在使用 JS 助手 我使用了以下代码
  • Python-在引号之间的字符串中插入数字

    我需要用数字本身替换字符串中的每个数字 但在引号之间 str This is number 1 and this is number 22 Result str This is number 1 and this is number 22
  • python 通用类型提示 + 用户定义的容器 + 约束实现 __add__ 方法的类型

    我想在 python 3 8 中以 Lisp 方式实现一个 Liste 类 其中包含 head 和 tail car cdr 和 nil 我想定义一个通用类型 接受 Liste 中类型 T 的对象 from future import an
  • 在 C 中使用 typedef struct 时取消引用指向不完整类型的指针错误

    include
  • CSS 选择器中的类名区分大小写吗?

    我一直在到处读到 CSS 不区分大小写 但我有这个选择器 holiday type Selfcatering 当我在 HTML 中使用它时 像这样 会被拾取 div class holiday type Selfcatering 如果我像这
  • H2O 目标均值编码器“帧按相同顺序发送”错误

    我按照 H2O 示例在 Sparking Water 中运行目标均值编码 sparking water 2 4 2 和 H2O 3 22 04 它在以下所有段落中运行良好 from h2o targetencoder import Targ
  • rdpmc:令人惊讶的行为

    我试图理解 rdpmc 指令 因此我有以下 asm 代码 segment text global start start xor eax eax mov ebx 10 loop dec ebx jnz loop mov ecx 1 lt l