【问题标题】:Write-combining: which cache line is avoided to be read before written?写入组合:避免在写入之前读取哪个缓存行?
【发布时间】:2013-03-12 18:32:36
【问题描述】:

关于非临时写入和写入组合技术,我有以下代码

void setbytes(char *p, int c)
{
__m128i i = _mm_set_epi8(c, c, c, c,
c, c, c, c,
c, c, c, c,
c, c, c, c);
_mm_stream_si128((__m128i *)&p[0], i);
_mm_stream_si128((__m128i *)&p[16], i);
_mm_stream_si128((__m128i *)&p[32], i);
_mm_stream_si128((__m128i *)&p[48], i);
}

取自here

上面写着

总而言之,这个代码序列不仅避免了读取缓存 在写入之前的行,它也避免了污染缓存 可能很快不需要的数据。这可以带来巨大的好处 某些情况。

我的问题是:避免写入哪个缓存行?存储 i 变量内容的缓存行还是 p 指针指向的缓存行(之后会被修改)?

【问题讨论】:

    标签: caching memory x86-64 intrinsics


    【解决方案1】:

    about: "避免在写入之前读取缓存行"

    该语句引用了用于处理未命中缓存的写入的“写入分配”策略。所有现代 x86 处理器都这样做。它是这样的:软件使用普通的 mov 指令写入内存。如果该地址已被缓存,则更新缓存并且根本没有 DRAM 访问。但是,如果数据不在高速缓存中,则处理器会从 DRAM 中读取该高速缓存行。然后将来自 mov 指令的数据合并到缓存中的数据中。处理器将尽可能长时间地推迟将该数据写回 DRAM。最终结果是违反直觉的:软件执行写入 (mov) 指令,并产生单个 DRAM 读取(突发)结果。如果这种模式重复,缓存最终会变满,需要驱逐来为读取腾出空间。在这种情况下,将有一个不相关的高速缓存行地址的 DRAM 写入突发,然后是软件正在写入的地址的读取。这解释了为什么非临时存储在填充大缓冲区时提供大约 2 倍的性能。与使用 mov 填充缓冲区相比,DRAM 访问次数只有一半。

    【讨论】:

      【解决方案2】:

      如果目标地址不在缓存中,则流式处理可以防止污染缓存,否则它只是根据需要使用写入该缓存行支持的地址的新值更新缓存。

      因此,在您的示例中,如果您尚未从 p 读取数据(或者您已使用 CLFLUSH 从缓存中刷新它),流式存储将阻止数据写入到 p 点被加载到的位置p 指向的地址的缓存(即:不会为写入的地址创建缓存线)。

      【讨论】:

      • 我明白了,但是它说“这个代码序列不仅避免在写入之前读取缓存行”的部分呢?您向我解释了“它还避免了可能很快不需要的数据污染缓存”
      • @JohnnyPauling: i 将被分配给一个寄存器,这意味着生成的代码中没有内存负载,因此它不会触发并在其进入​​时为其创建缓存行使用。
      猜你喜欢
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 1970-01-01
      • 2017-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-16
      相关资源
      最近更新 更多