我知道关于这个主题的多个问题,但是,我没有看到任何明确的答案或任何基准测量.因此,我创建了一个简单的程序,它使用两个整数数组.第一个数组a
非常大(64 MB),第二个数组b
很小,适合L1缓存.程序迭代a
并将其元素添加到b
模块化意义上的相应元素中(当到达结束时b
,程序从其开始再次开始).测量的不同大小的L1缓存未命中数b
如下:
测量是在具有32 kiB L1数据高速缓存的Xeon E5 2680v3 Haswell型CPU上进行的.因此,在所有情况下,都b
适合L1缓存.然而,大约16 kiB的b
内存占用量大大增加了未命中数.这可能因为两者的负载预期a
并b
导致缓存线失效从一开始b
在这一点上.
绝对没有理由保留a
缓存中的元素,它们只使用一次.因此,我运行一个具有非时间负载a
数据的程序变体,但未命中数没有改变.我还运行了一个非暂时预取a
数据的变体,但仍然有相同的结果.
我的基准代码如下(没有显示非时间预取的变体):
int main(int argc, char* argv[])
{
uint64_t* a;
const uint64_t a_bytes = 64 * 1024 * 1024;
const uint64_t a_count = a_bytes / sizeof(uint64_t);
posix_memalign((void**)(&a), 64, a_bytes);
uint64_t* b;
const uint64_t b_bytes = atol(argv[1]) * 1024;
const uint64_t b_count = b_bytes …
Run Code Online (Sandbox Code Playgroud) 当从连续的内存位置执行一系列_mm_stream_load_si128()
调用(MOVNTDQA
)时,硬件预取器是否仍会启动,或者我应该使用显式软件预取(使用NTA提示)以获得预取的好处,同时仍然避免缓存污染?
我问这个的原因是因为他们的目标似乎与我相矛盾.流加载将获取绕过缓存的数据,而预取器尝试主动将数据提取到缓存中.
当顺序迭代一个大型数据结构(处理过的数据不会在很长一段时间内被修饰)时,我有必要避免污染chache层次结构,但我不想因频繁出现频繁的~100次循环处罚-fetcher闲置.
目标架构是Intel SandyBridge
通过使用内存标记为WB指令之间的主要区别是什么(回写)和WC(写入合并):什么是之间的不同MOVDQA
和MOVNTDQA
,什么是之间的不同VMOVDQA
和VMOVNTDQ
?
是不是对于内存标记为WC - 指令与[NT]
通常没有区别(没有[NT]
),并且内存标记为WB - 指令[NT]
与它一起工作就好像它是一个内存WC?
Write-Combine缓冲区是如何物理连接的?我已经看到了说明许多变体的方框图:
它是依赖于微架构的吗?
将数据写入 PCIe 设备时,可以使用写入组合映射来提示 CPU 应该向设备生成 64 字节的 TLP。
是否可以为读取做类似的事情?以某种方式提示 CPU 读取整个缓存行或更大的缓冲区,而不是一次读取一个字?
我想将一些代码预取到指令缓存中.代码路径很少使用,但我需要它在指令缓存中,或者至少在L2中用于极少数情况下使用它.我预先通知了这些罕见的情况._mm_prefetch是否适用于代码?有没有办法在缓存中获得这种不经常使用的代码?对于这个问题,我不关心可移植性,所以即使asm会这样做.
x86 ×6
prefetch ×3
c++ ×2
cpu-cache ×2
sse ×2
assembly ×1
avx ×1
c ×1
caching ×1
intel ×1
low-latency ×1
optimization ×1
pci-e ×1
performance ×1
simd ×1