1

我有核心 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() 以查找访问时间。我从i3 或 i7 处理器中的这个链接 clflush()了解了在 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.
    

尽管我在 Scenario-1 中获得了预期的结果,但在 clflush 之后访问数组元素的访问时间并没有增加。

是什么原因 ?如何过来了解驱逐后的正确访问时间。听说过硬件和软件预取,它们会影响我的结果吗?如何克服那里的影响并了解正确的结果?

4

1 回答 1

1

在通过 bios(或任何其他方式)禁用硬件预取器后尝试重新运行。您描述了一个非常稳定的流,它会立即被硬件流预取器识别,并在加载之前很好地提取(使访问时间与常规 L2 查找完全相同)

于 2013-10-14T13:16:27.367 回答