【发布时间】:2013-10-05 14:49:52
【问题描述】:
我有核心 i7 系统,其 L1 缓存大小为 32KB,L2 缓存大小为 256KB,共享 L3 缓存大小为 8MB(在 4 个内核之间共享)。 我编写了一个程序,在其中按顺序执行 A、B、C 部分。 (A) 创建一个大小为 L2 缓存 4 倍的大 int 数组,并访问大数组的每 16 个元素(缓存行大小为 64B,16*4 B=64B),以确保我所有的数据都加载到 L2 中。记下大数组 (B) 的每个元素的访问时间,然后使用 clflush 从我的数据数组的多个位置手动逐出数据,例如 clflush(&bigarray[0]) ...clflush (&bigarray[1024])。 (C) 再次访问大数组的每个第 16 个元素,包括在 (B) 中手动驱逐的那些行。
我在访问我的大数组的行之前和之后放置了 rdtsc() 以查找访问时间。我通过此链接clflush() in i3 or i7 processors了解了在 i3/i7 机器中使用 clflush
asm volatile ("cpuid; rdtsc" : "=a" (a), "=d" (d) : : "ebx", "ecx");
如预期的那样,我在单行驱逐后获得了更长的访问时间,令我惊讶的是,多个位置的访问时间没有增加。
让我换个方式解释一下:
场景1:在clflush前后访问单个数组元素
- step1- 访问 (a[x]) 并找到访问时间
- step2- 使用 clflush(&a[x]) 将其从缓存中逐出并查找访问时间
场景2:在clflush前后访问多个数组元素
- step1- 访问数组的每个元素 a[i]
-
第 2 步-
for all i { clflush( &a[i]) } to evict from cache and find access time of all elements at i.
在 clflush 之后,我没有获得更长的访问时间来访问数组元素,尽管我得到了 Scenario-1 中的预期结果。
是什么原因?如何过来了解驱逐后的正确访问时间。听说过硬件和软件预取,它们会影响我的结果吗?如何克服那里的影响并了解正确的结果?
【问题讨论】: