存储指令是否会阻止缓存未命中的后续指令?
Do store instructions block subsequent instructions on a cache miss?
假设我们有一个处理器,有两个内核(C0 和 C1(,并且从地址k
开始的缓存行最初由 C0 拥有。如果 C1 在第k
行的 8 字节插槽上发出存储指令,这是否会影响在 C1 上执行的以下指令的吞吐量?
英特尔优化手册有以下段落
当指令将数据写入内存位置 [...] 时,处理器确保包含此内存位置的行位于其 L1d 缓存 [...] 中。如果缓存行不存在,它使用 RFO 请求从下一级获取 [...]RFO 和数据存储发生在指令停用后。 因此,存储延迟通常不会影响存储指令本身
参考以下代码,
// core c0
foo();
line(k)->at(i)->store(kConstant, std::memory_order_release);
bar();
baz();
英特尔手册中的引用使我假设在上面的代码中,代码的执行看起来好像存储本质上是无操作的,并且不会影响foo()
结束和bar()
开始之间的延迟。 相反,对于以下代码,
// core c0
foo();
bar(line(k)->at(i)->load(std::memory_order_acquire));
baz();
foo()
结束和bar()
开始之间的延迟将受到负载的影响,因为以下代码将加载的结果作为依赖项。
这个问题主要关注英特尔处理器(在 Broadwell 系列或更新中(如何在上述情况下工作。 此外,特别是,对于如何编译C++类似于上述内容的代码,这些处理器的汇编。
一般来说,对于后续代码不会很快读取的商店,商店不会直接延迟任何现代无序处理器(包括英特尔(上的后续代码。
例如:
foo()
*x = y;
bar()
如果foo()
不修改x
或y
,并且bar
不从*x
加载,则存储是独立的,甚至可以在foo()
完成之前(甚至在启动之前(开始执行,并且bar()
可能在存储提交到缓存之前执行,bar()
甚至可以在foo()
运行时执行, 等。
虽然几乎没有直接影响,但这并不意味着没有间接影响,事实上商店可能会主导执行时间。
如果存储未命中缓存,则可能会在满足缓存未命中时占用核心外资源。它通常还可以防止后续存储耗尽,这可能是一个瓶颈:如果存储缓冲区填满,前端完全阻塞,新指令不再进入调度程序。
最后,像往常一样,一切都取决于周围代码的细节。如果重复运行该序列,并且foo()
和bar()
较短,则与存储相关的未命中可能会主导运行时。毕竟,缓冲无法隐藏无限数量商店的成本。在某些时候,您将受到商店的内在吞吐量的约束。
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- C++:对不存在的命名空间使用命名空间指令
- cmake更新缓存的变量
- 试图对缓存进行跨步测试,但程序并没有结束
- 函数名是c中该函数的第一条指令的地址吗
- 缓存std::数组的选定元素,并在c++中自动保持其一致性
- 通过ccmake在cmake中缓存依赖选项
- 错误:无效的预处理指令 #i 的意思是 #if?
- 组装指令中乘法的下部和上部是什么
- OpenMP 与有序和关键指令并行
- C++中的移动分配出现问题.非法指令: 4.
- 嵌套命名空间的"using"指令,但需要命名内部命名空间
- 使用宏扩展的泛型:为什么指令缓存使用不当?
- 存储指令是否会阻止缓存未命中的后续指令?
- 减少指令缓存错过(在C 中)
- 为什么我的代码会导致指令缓存未命中
- clflush不刷新指令缓存
- 指令高速缓存和条件语句
- 如何用C ++编写指令缓存友好程序