假设我们有一个具有两个核心(C0 和 C1)的处理器和一个从地址开始的高速缓存行k
最初由 C0 拥有。如果 C1 在第 8 行的 8 字节槽上发出存储指令k
,这会影响 C1 上执行的以下指令的吞吐量吗?
intel优化手册有如下一段
当指令将数据写入内存位置 [...] 时,处理器确保包含该内存位置的行位于其 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++ 代码编译为这些处理器的程序集。
一般来说,对于后续代码不会很快读取到的 store,该 store 不会directly延迟任何现代乱序处理器(包括英特尔)上的后续代码。
例如:
foo()
*x = y;
bar()
If foo()
不修改x
or y
, and bar
不加载自*x
,商店是独立的,甚至可以在之前开始执行foo()
已完成(或什至在开始之前),并且bar()
可以在存储提交到缓存之前执行,并且bar()
甚至可能执行 whilefoo()
正在运行等
虽然有一点点direct影响,并不意味着没有间接影响,实际上存储可能会主导执行时间。
如果缓存中的存储未命中,则在满足缓存未命中的情况下可能会占用非核心资源。它通常还可以防止后续存储耗尽,这可能是一个瓶颈:如果存储缓冲区已满,则前端完全阻塞,并且新指令不再进入调度程序。
最后,像往常一样,一切都取决于周围代码的细节。如果重复运行该序列,并且foo()
and bar()
很短,与存储相关的未命中可能会主导运行时。毕竟,缓冲无法掩盖无限数量存储的成本。在某些时候,您将受到商店固有吞吐量的限制。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)