gpt4 book ai didi

c - 如何强制 cpu 核心刷新 c 中的存储缓冲区?

转载 作者:行者123 更新时间:2023-12-01 15:32:45 25 4
gpt4 key购买 nike

我有一个应用程序,它有 2 个线程,线程 A 与核心 1 的关联性和线程 B 与核心 2 的关联性,
核心 1 和核心 2 在同一个 x86 插槽中。

线程 A 忙于整数 x 的自旋,线程 B 在某些情况下会增加 x,当线程 B 决定增加 x 时,它会使 x 所在的缓存行失效,并根据 x86 MESI 协议(protocol)存储新的 x 存储缓冲区在 core2 接收到无效 ack 之前,然后在 core2 接收到无效 ack 之后,core2 刷新存储缓冲区。

我想知道,core2 收到无效确认后是否立即刷新存储缓冲区?!有没有机会我可以强制 cpu 用 ​​c 语言刷新存储缓冲区?!因为在我的情况下,core1 spining x 中的线程 A 应该尽早获得 x 新值。

最佳答案

核心总是尽可能快地将其存储缓冲区提交到 L1d 缓存(因此变得全局可见),以便为更多存储腾出空间。
您可以使用屏障(如 atomic_thread_fence(memory_order_seq_cst )使线程等待其存储在进行任何更多加载或存储之前变为全局可见,但这通过阻塞该核心而不是通过加速刷新存储缓冲区来工作。
显然,为了避免 C11 中未定义的行为,变量必须是 _Atomic .如果只有一位作者,您可以使用 tmp = atomic_load_explicit(&x, memory_order_relaxed)tmp+1 的 store_explicit以避免更昂贵的 seq_cst 存储或原子 RMW。 acq/rel 排序也可以,只是避免使用默认的 seq_cst,并避免使用 atomic_fetch_add如果只有一位作家,RMW。
如果只有一个线程修改它,而其他线程以只读方式访问它,则不需要整个 RMW 操作是原子的。

在另一个核心可以读取您写入的数据之前,它必须从将其写入 L3 缓存的核心的 L1d 中的修改状态,然后从那里到达读取器核心的 L1d。
您也许可以加快这部分的速度,这发生在数据离开存储缓冲区之后。但是你能做的有用的不多。你不想 clflush/clflushopt ,这将完全回写+逐出缓存行,因此如果其他内核在此过程中没有尝试读取它(如果可能的话),则必须从DRAM中获取它。
冰湖有 clwb 这(希望)将数据缓存并强制写回DRAM。但这再次迫使数据实际上一直传输到 DRAM,而不仅仅是共享的外部缓存,因此它会消耗 DRAM 带宽并且可能比我们想要的要慢。 (Skylake-Xeon 也有,但是 handles it the same as clflushopt 。我期待并希望 Ice Lake 客户端/服务器有/将有一个正确的实现。)

Tremont (successor to Goldmont Plus , atom/silvermont系列 ) 有 _mm_cldemote ( cldemote )。这与 SW 预取相反;将缓存线写入 L3 是可选的性能提示,但不会强制它进入 DRAM 或其他任何东西。

如果没有特殊说明,也许您可​​以写入在 L2 和 L1d 缓存中别名相同集合的 8 个其他位置,从而强制冲突驱逐 .这将在写入线程中花费额外的时间,但可以使数据更快地提供给其他想要读取它的线程。我没试过这个。
这也可能会驱逐其他线路,花费更多的 L3 流量 = 系统范围的共享资源,而不仅仅是在生产者线程中花费时间。您只会考虑延迟,而不是吞吐量,除非其他行是您想要编写和驱逐的行。

关于c - 如何强制 cpu 核心刷新 c 中的存储缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54067605/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com