- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我很难解读英特尔性能事件报告。
考虑以下主要读取/写入内存的简单程序:
#include <stdint.h>
#include <stdio.h>
volatile uint32_t a;
volatile uint32_t b;
int main() {
printf("&a=%p\n&b=%p\n", &a, &b);
for(size_t i = 0; i < 1000000000LL; i++) {
a ^= (uint32_t) i;
b += (uint32_t) i;
b ^= a;
}
return 0;
}
我用gcc -O2
编译它并在perf
下运行:
# gcc -g -O2 a.c
# perf stat -a ./a.out
&a=0x55a4bcf5f038
&b=0x55a4bcf5f034
Performance counter stats for 'system wide':
32,646.97 msec cpu-clock # 15.974 CPUs utilized
374 context-switches # 0.011 K/sec
1 cpu-migrations # 0.000 K/sec
1 page-faults # 0.000 K/sec
10,176,974,023 cycles # 0.312 GHz
13,010,322,410 instructions # 1.28 insn per cycle
1,002,214,919 branches # 30.699 M/sec
123,960 branch-misses # 0.01% of all branches
2.043727462 seconds time elapsed
# perf record -a ./a.out
&a=0x5589cc1fd038
&b=0x5589cc1fd034
[ perf record: Woken up 3 times to write data ]
[ perf record: Captured and wrote 0.997 MB perf.data (9269 samples) ]
# perf annotate
perf annotate
的结果(由我注释内存加载/存储):
Percent│ for(size_t i = 0; i < 1000000000LL; i ++) {
│ xor %eax,%eax
│ nop
│ a ^= (uint32_t) i;
│28: mov a,%edx // 32-bit load
│ xor %eax,%edx
9.74 │ mov %edx,a // 32-bit store
│ b += (uint32_t) i;
12.12 │ mov b,%edx // 32-bit load
8.79 │ add %eax,%edx
│ for(size_t i = 0; i < 1000000000LL; i ++) {
│ add $0x1,%rax
│ b += (uint32_t) i;
18.69 │ mov %edx,b // 32-bit store
│ b ^= a;
0.04 │ mov a,%ecx // 32-bit load
22.39 │ mov b,%edx // 32-bit load
8.92 │ xor %ecx,%edx
19.31 │ mov %edx,b // 32-bit store
│ for(size_t i = 0; i < 1000000000LL; i ++) {
│ cmp $0x3b9aca00,%rax
│ ↑ jne 28
│ }
│ return 0;
│ }
│ xor %eax,%eax
│ add $0x8,%rsp
│ ← retq
我的观察:
insn 每周期
我得出结论,该程序主要受内存限制。a
和 b
似乎位于同一缓存行中,彼此相邻。我的问题:
mov a,%edx
) 的 CPU 时间为零?mov a,%ecx
的时间是 0.04%,而紧邻的一个 mov b,%edx
的时间是 22.39%?<注释:
操作系统:Linux 4.19.0-amd64,CPU:Intel Core i9-9900K,100%空闲系统(也在i7-7700上测试,结果相同)。
最佳答案
不完全是“内存”限制,而是存储转发延迟的限制。 i9-9900K 和 i7-7700 每个核心的微架构完全相同,因此这并不奇怪:P https://en.wikichip.org/wiki/intel/microarchitectures/coffee_lake#Key_changes_from_Kaby_Lake 。 (除了可能改进硬件缓解 Meltdown 的方法,以及可能修复循环缓冲区 (LSD) 之外。)
请记住,当性能事件计数器溢出并触发样本时,无序超标量 CPU 必须准确选择一条正在运行的指令来“归咎”此周期
事件。通常,这是 ROB 中最旧的未退役指令,或之后的指令。对非常小规模的cycles
事件样本保持高度怀疑。
Perf 永远不会责怪产生结果缓慢的负载,通常是正在等待它的指令。 (在本例中为xor
或add
)。在这里,有时存储会消耗该异或的结果。这些不是缓存未命中加载;而是缓存未命中加载。 Skylake 上的存储转发延迟仅为大约 3 到 5 个周期(可变,如果您不尽快尝试的话会更短: Loop with function call faster than an empty loop ),因此您确实每 3 到 5 个周期完成大约 2 个负载。
内存中有两个依赖链
b
的两个 RMW。这是两倍长,并且将成为循环的整体瓶颈。a
的一个 RMW(每次迭代都有一次额外的读取,这可能与下一个 a ^= i;
的一部分的读取并行发生) .i
的 dep 链仅涉及寄存器,并且可以远远领先于其他链;毫不奇怪,add $0x1,%rax
没有计数。它的执行成本完全隐藏在等待加载的阴影中。
我有点惊讶 mov %edx,a
的计数很高。也许有时必须等待涉及 b
的旧存储 uops 在 CPU 的单个存储数据端口上运行。 (Uops按照最旧的就绪优先调度到端口。How are x86 uops scheduled, exactly?)
Uops 在之前的所有 uops 都执行完毕之前无法退出,因此它可能只是从循环底部的存储中获得一些偏差。 Uops 以 4 组为一组退出,因此如果 mov %edx,b 确实退出,则已执行的 cmp/jcc、a
的 mov 负载以及 >xor %eax,%edx
可以随之退出。这些不是等待 b
的 dep 链的一部分,因此每当 b
商店准备退出时,它们总是坐在 ROB 中等待退出。 (这是关于 mov %edx,a
如何获取计数的猜测,尽管不是真正瓶颈的一部分。)
存储地址微指令应该全部运行在循环之前,因为它们不必等待先前的迭代:RIP 相对寻址1 立即准备就绪。它们可以在端口 7 上运行,或者与端口 2 或 3 的负载竞争。对于负载也是如此:它们可以立即执行并检测它们正在等待的存储,负载缓冲区会监视它并准备好报告何时存储数据 uop 最终运行后,数据准备就绪。
大概前端最终会在分配加载缓冲区条目时遇到瓶颈,这将限制后端可以有多少微指令,而不是 ROB 或 RS 大小。
脚注 1:带注释的输出仅显示 a
而不是 a(%rip)
,所以这很奇怪;如果您以某种方式让它使用 32 位绝对值,或者只是反汇编怪癖而未能显示 RIP 相对值,这并不重要。
关于performance - `perf annotate` 内存加载/存储时间报告不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65906312/
我想要显示正在加载的 .gif,直到所有内容都已加载,包括嵌入的 iframe。但是,目前加载 gif 会在除 iframe 之外的所有内容都已加载后消失。我怎样才能让它等到 iframe 也加载完毕
首先,这是我第一次接触 Angular。 我想要实现的是,我有一个通知列表,我必须以某种方式限制 limitTo,因此元素被限制为三个,在我单击按钮后,其余的应该加载。 我不明白该怎么做: 设置“ V
我正在尝试在我的设备上运行这个非常简单的应用程序(使用 map API V2),并且出于某种原因尝试使用 MapView 时: 使用 java 文件: public class MainMap e
我正在使用 Python 2.6、Excel 2007 Professional 和最新版本的 PyXLL。在 PyXLL 中加载具有 import scipy 抛出异常,模块未加载。有没有人能够在
我想做这个: 创建并打包原始游戏。然后我想根据原始游戏中的蓝图创建具有新网格/声音/动画和蓝图的其他 PAK 文件。原始游戏不应该知道有关其他网格/动画/等的任何信息。因此,我需要在原始游戏中使用 A
**摘要:**在java项目中经常会使用到配置文件,这里就介绍几种加载配置文件的方法。 本文分享自华为云社区《【Java】读取/加载 properties配置文件的几种方法》,作者:Copy工程师。
在 Groovy 脚本中是否可以执行条件导入语句? if (test){ import this.package.class } else { import that.package.
我正在使用 NVidia 视觉分析器(来自 CUDA 5.0 beta 版本的基于 eclipse 的版本)和 Fermi 板,我不了解其中两个性能指标: 全局加载/存储效率表示实际内存事务数与请求事
有没有办法在通过 routeProvider 加载特定 View 时清除 Angular JS 存储的历史记录? ? 我正在使用 Angular 创建一个公共(public)安装,并且历史会积累很多,
使用 Xcode 4.2,在我的应用程序中, View 加载由 segue 事件触发。 在 View Controller 中首先调用什么方法? -(void) viewWillAppear:(BOO
我在某些Django模型中使用JSONField,并希望将此数据从Oracle迁移到Postgres。 到目前为止,当使用Django的dumpdata和loaddata命令时,我仍然没有运气来保持J
创建 Nib 时,我需要创建两种类型:WindowNib 或 ViewNib。我看到的区别是,窗口 Nib 有一个窗口和一个 View 。 如何将 View Nib 加载到另一个窗口中?我是否必须创建
我想将多个env.variables转换为静态结构。 我可以手动进行: Env { is_development: env::var("IS_DEVELOPMENT")
正如我从一个测试用例中看到的:https://godbolt.org/z/K477q1 生成的程序集加载/存储原子松弛与普通变量相同:ldr 和 str 那么,宽松的原子变量和普通变量之间有什么区别吗
我有一个重定向到外部网站的按钮/链接,但是外部网站需要一些时间来加载。所以我想添加一个加载屏幕,以便外部页面在显示之前完全加载。我无法控制外部网站,并且外部网站具有同源策略,因此我无法在 iFrame
我正在尝试为我的应用程序开发一个Dockerfile,该文件在初始化后加载大量环境变量。不知何故,当我稍后执行以下命令时,这些变量是不可用的: docker exec -it container_na
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我刚刚遇到一个问题,我有一个带有一些不同选项的选择标签。 现在我想检查用户选择了哪些选项。 然后我想将一个新的 html 文件加载到该网站(取决于用户选中的选项)宽度 javascript,我该怎么做
我知道两种保存/加载应用程序设置的方法: 使用PersistentStore 使用文件系统(存储,因为 SDCard 是可选的) 我想知道您使用应用程序设置的做法是什么? 使用 PersistentS
我开始使用 Vulkan 时偶然发现了我的第一个问题。尝试创建调试报告回调时(验证层和调试扩展在我的英特尔 hd vulkan 驱动程序上可用,至少它是这么说的),它没有告诉我 vkCreateDeb
我是一名优秀的程序员,十分优秀!