我正在阅读Ulrich Drepper的PDF文件《程序员应该了解的有关内存的一切》。在第6部分的开头,有一个代码片段:
在此注释下方有这样一段话:
假设指针p的对齐方式正确,调用此函数将会把所访问的缓存行中的所有字节都设置为c。写组合逻辑将会看到生成的四个movntdq指令,并且只有在执行最后一个指令之后才会发出内存写命令。总之,这段代码序列不仅避免了在写入之前读取缓存行,还避免了将可能不需要的数据污染到缓存中。
我困扰的是,在该函数的注释中写道“将设置所访问的缓存行中的所有字节为c”,但据我所知,流内置函数会绕过缓存 - 既没有缓存读取也没有缓存写入。这段代码如何访问任何缓存行?第二个加粗片段说得类似,即该函数“避免在写入之前读取缓存行”。如上所述,我看不到任何缓存何时以及何时被写入。另外,任何对缓存的写入是否需要先进行缓存写入?能否有人向我澄清这个问题?
#include <emmintrin.h>
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);
}
在此注释下方有这样一段话:
假设指针p的对齐方式正确,调用此函数将会把所访问的缓存行中的所有字节都设置为c。写组合逻辑将会看到生成的四个movntdq指令,并且只有在执行最后一个指令之后才会发出内存写命令。总之,这段代码序列不仅避免了在写入之前读取缓存行,还避免了将可能不需要的数据污染到缓存中。
我困扰的是,在该函数的注释中写道“将设置所访问的缓存行中的所有字节为c”,但据我所知,流内置函数会绕过缓存 - 既没有缓存读取也没有缓存写入。这段代码如何访问任何缓存行?第二个加粗片段说得类似,即该函数“避免在写入之前读取缓存行”。如上所述,我看不到任何缓存何时以及何时被写入。另外,任何对缓存的写入是否需要先进行缓存写入?能否有人向我澄清这个问题?
movntdq
可以在缓存中命中,但是如果该行存在,则会将其从缓存中驱逐。我猜这个设计决策是为了让驱动程序在对视频内存进行NT存储后避免使用clflush
。(如果我没记错的话,文档说早期支持该指令的CPU上不会发生这种保证性的驱逐。) - Peter Cordes