关于非时间写入和写入组合技术,我有以下代码
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指针所指向的缓存行(之后会被修改)?
答案 0 :(得分:3)
about:“避免在写入之前读取缓存行”
此语句引用“写入分配”策略来处理错过缓存的写入。所有现代x86处理器都是这样做的。它是这样的:软件使用普通的mov指令写入内存。如果该地址已被缓存,则更新缓存并且根本没有DRAM访问。但是,如果数据不在缓存中,则处理器从DRAM读取该缓存行。然后将来自mov指令的数据合并到缓存中的数据中。处理器将推迟尽可能长时间地将数据写回DRAM。最终结果是违反直觉的:软件执行写(mov)指令,并产生单个DRAM读(突发)结果。如果重复此模式,缓存最终将变满,并且需要驱逐以为读取腾出空间。在这种情况下,将存在无关高速缓存行地址的DRAM写突发,然后读取软件正在写入的地址。这解释了为什么非临时存储为填充大缓冲区提供了大约2倍的性能。与使用mov填充缓冲区相比,只有一半的DRAM访问次数出现。
答案 1 :(得分:1)
如果目标地址不在缓存中,则流可以防止污染缓存,否则只需根据需要更新缓存,新值写入该缓存行支持的地址。
所以在你的例子中,如果你没有从p
读取(或者你用CLFLUSH
从缓存刷新了它),流式存储将阻止数据写入{{1}被加载到p
指向的地址的缓存中的点(即:将不会为写入的地址创建cachline)。