[英]Why 16 stepping by 4K in main memory causing no L1d cache miss
我在IvyBridge上,想测试L1d缓存组织。 我的理解如下:
在IvyBridge上,L1d缓存具有32K容量,64B缓存行,8种方式关联。 因此,它具有32K /(64 * 8)= 64组,给定一个主内存addr
,则可以通过(addr/64) % 64
计算该组索引。
因此,如果我将主存储器调高64 * 64(4K),我将始终触摸同一L1d集。 一个集合只有8个缓存行,因此,如果我用16个步骤循环它,我将得到几乎100%的L1d缓存未命中。
我编写以下程序进行验证:
section .bss
align 4096
buf: resb 1<<26
%define gap 64 * 64 ; no L1 cache miss
; %define gap 64 * 64 * 256 ; 41% L1 cache miss
; %define gap 64 * 64 * 512 ; 95% L1 cache miss
; however, total cycle suggests this gap is already at L3 latency level with complete L2 cache miss.
section .text
global _start
_start:
mov rcx, 10000000
xor rax, rax
loop:
mov rax, [buf+rax]
mov rax, [buf+rax+gap*1]
mov rax, [buf+rax+gap*2]
mov rax, [buf+rax+gap*3]
mov rax, [buf+rax+gap*4]
mov rax, [buf+rax+gap*5]
mov rax, [buf+rax+gap*6]
mov rax, [buf+rax+gap*7]
mov rax, [buf+rax+gap*8]
mov rax, [buf+rax+gap*9]
mov rax, [buf+rax+gap*10]
mov rax, [buf+rax+gap*11]
mov rax, [buf+rax+gap*12]
mov rax, [buf+rax+gap*13]
mov rax, [buf+rax+gap*14]
mov rax, [buf+rax+gap*15]
dec rcx,
jne loop
xor rdi, rdi
mov rax, 60
syscall
令我惊讶的是, perf
显示根本没有丢失L1缓存:
160,494,057 L1-dcache-loads
4,290 L1-dcache-load-misses # 0.00% of all L1-dcache hits
我的理解有什么问题?
最初,所有BSS页面都被写时复制映射到相同的物理零页面。 您会遇到TLB遗漏(甚至可能是软页面错误),但是没有L1d遗漏。
为避免这种情况并将它们映射到不同的物理页面:
mmap(MAP_POPULATE)
分配而不是使用BSS。 这将至少对它们进行预故障处理,避免出现软页面错误,但仍可能会出现相同的物理零页面。 buf
放在.data
或.rodata
节中,实际上将在其中将其与文件支持进行映射。 (您必须使其更小,因为零实际上将在可执行文件中)。 (对我而言)更有趣的结果是,您确实开始获得跨步较大的缓存未命中 。 然后,您将访问更多的4k页面,这可能导致内核开始为您的BSS使用2M巨大页面,具有讽刺意味的是,它不再使它们成为同一4k物理页面的别名,从而损害了它。 您可以检查/proc/PID/smaps
以查看该映射是否存在非零的AnonHuge。
由于L2也是8路关联的,因此可能会错过L2,但是L3关联性更高,并且使用非简单的索引功能,该函数将2步的简单幂分布在多个集合上。 ( intel核心i7处理器中使用了哪种缓存映射技术? )
顺便说一句,您可能想要的间隔不是2的幂。只是L1别名跨度的倍数,而不是L2别名跨度的倍数,因此您的数据可以通过L2中的许多集合分布。
我一直在寻找重复项,但没有找到确切的重复项,尽管我很确定自己在SO>。<之前已经对此进行了解释。 可能我正在考虑如何在此循环中获得一致的高吞吐量? malloc正是这个问题,而不是BSS。
有关:
mremap
的零页虚拟内存/ COW有一些好处。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.