3

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

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);
}

取自这里

上面写着

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

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

4

2 回答 2

4

关于:“避免在写入之前读取缓存行”

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

于 2013-03-25T05:36:53.550 回答
1

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

所以在你的例子中,如果你没有从缓存中读取p(或者你已经从缓存中刷新它CLFLUSH),流存储将阻止数据被写入到p被加载到缓存中的点的位置,以获取指向的地址p(即:否将为写入的地址创建缓存线)。

于 2013-03-22T20:07:55.000 回答