Cur*_*ous 5 c++ concurrency x86 cpu-architecture cpu-cache
假设我们有一个处理器,它有两个内核(C0 和 C1)和一个从k最初由 C0 拥有的地址开始的缓存线。如果 C1 在第 8 字节槽上发出一条存储指令k,是否会影响在 C1 上执行的后续指令的吞吐量?
intel优化手册有以下一段
当一条指令将数据写入内存位置 [...] 时,处理器会确保包含该内存位置的行位于其 L1d 缓存中 [...]。如果缓存线不存在,它会使用 RFO 请求 [...] RFO 从下一级获取数据,并在指令退出后存储数据。因此,存储延迟通常不会影响存储指令本身
参考以下代码,
// core c0
foo();
line(k)->at(i)->store(kConstant, std::memory_order_release);
bar();
baz();
Run Code Online (Sandbox Code Playgroud)
从英特尔手动使得报价我认为在上面的代码,代码的执行将看起来像是商店基本上是一个空操作,和结束之间会不会影响延迟foo()和开始bar()。相比之下,对于下面的代码,
// core c0
foo();
bar(line(k)->at(i)->load(std::memory_order_acquire));
baz();
Run Code Online (Sandbox Code Playgroud)
结束foo()和开始之间的延迟bar()会受到加载的影响,因为以下代码将加载结果作为依赖项。
这个问题主要与英特尔处理器(在 Broadwell 系列或更新版本中)如何在上述情况下工作有关。此外,特别是关于如何将类似于上述的 C++ 代码编译为这些处理器的汇编。
一般来说,对于后续代码不会很快读取的存储,存储不会直接延迟任何现代乱序处理器(包括英特尔)上的后续代码。
例如:
foo()
*x = y;
bar()
Run Code Online (Sandbox Code Playgroud)
如果foo()不修改x或y,并且bar不从 加载*x,则存储是独立的,甚至可能在foo()完成之前(甚至在它开始之前)就开始bar()执行,并且可能在存储提交到缓存之前bar()执行,甚至可能同时执行foo()正在运行等
虽然几乎没有直接影响,但这并不意味着没有间接影响,而且实际上商店可能会支配执行时间。
如果存储在缓存中未命中,则在满足缓存未命中时,它可能会占用核外资源。它通常还可以防止后续存储耗尽,这可能是一个瓶颈:如果存储缓冲区填满,前端会完全阻塞并且新指令不再进入调度程序。
最后,一切都取决于周围代码的细节,就像往常一样。如果该序列重复运行foo()并且bar()很短,则与存储相关的未命中可能会支配运行时间。毕竟,缓冲无法隐藏无限数量的商店的成本。在某些时候,您将受到商店的内在吞吐量的约束。
| 归档时间: |
|
| 查看次数: |
153 次 |
| 最近记录: |