Caching 什么是;“页面错误”;在'perf stat'中,是指;“后端循环空闲”吗;?

Caching 什么是;“页面错误”;在'perf stat'中,是指;“后端循环空闲”吗;?,caching,perf,Caching,Perf,我编写了一个简单的矩阵乘法程序来演示通过perf进行缓存和性能测量的效果。比较相对效率的两个函数是sqmat\u mult和sqmat\u mult\u efficient: void sqmat_mult(整数x,常数a[x][x],常数b[x][x],整数m[x][x]) { 对于(int i=0;i

我编写了一个简单的矩阵乘法程序来演示通过perf进行缓存和性能测量的效果。比较相对效率的两个函数是
sqmat\u mult
sqmat\u mult\u efficient

void sqmat_mult(整数x,常数a[x][x],常数b[x][x],整数m[x][x])
{
对于(int i=0;i
然而,当我基于这两个函数运行
perf stat
时,我对“页面错误”统计信息感到困惑。
sqmat\u mult
的输出为:

     428374.070363      task-clock (msec)         #    1.000 CPUs utilized          
               128      context-switches          #    0.000 K/sec                  
               127      cpu-migrations            #    0.000 K/sec                  
            12,334      page-faults               #    0.029 K/sec                  
 8,63,12,33,75,858      cycles                    #    2.015 GHz                      (83.33%)
    2,89,73,31,370      stalled-cycles-frontend   #    0.34% frontend cycles idle     (83.33%)
 7,90,36,10,13,864      stalled-cycles-backend    #   91.57% backend cycles idle      (33.34%)
 2,24,41,64,76,049      instructions              #    0.26  insn per cycle         
                                                  #    3.52  stalled cycles per insn  (50.01%)
    8,84,30,79,219      branches                  #   20.643 M/sec                    (66.67%)
       1,04,85,342      branch-misses             #    0.12% of all branches          (83.34%)

     428.396804101 seconds time elapsed
       8534.611199      task-clock (msec)         #    1.000 CPUs utilized          
      39876.726670      task-clock (msec)         #    1.000 CPUs utilized          
                11      context-switches          #    0.000 K/sec                  
                11      cpu-migrations            #    0.000 K/sec                  
            12,334      page-faults               #    0.309 K/sec                  
 1,19,87,36,75,397      cycles                    #    3.006 GHz                      (83.33%)
      49,19,07,231      stalled-cycles-frontend   #    0.41% frontend cycles idle     (83.33%)
   50,40,53,90,525      stalled-cycles-backend    #   42.05% backend cycles idle      (33.35%)
 2,24,10,77,52,356      instructions              #    1.87  insn per cycle         
                                                  #    0.22  stalled cycles per insn  (50.01%)
    8,75,27,87,494      branches                  #  219.496 M/sec                    (66.68%)
         50,48,390      branch-misses             #    0.06% of all branches          (83.33%)

      39.879816492 seconds time elapsed
sqmat\u mult\u efficient
的输出为:

     428374.070363      task-clock (msec)         #    1.000 CPUs utilized          
               128      context-switches          #    0.000 K/sec                  
               127      cpu-migrations            #    0.000 K/sec                  
            12,334      page-faults               #    0.029 K/sec                  
 8,63,12,33,75,858      cycles                    #    2.015 GHz                      (83.33%)
    2,89,73,31,370      stalled-cycles-frontend   #    0.34% frontend cycles idle     (83.33%)
 7,90,36,10,13,864      stalled-cycles-backend    #   91.57% backend cycles idle      (33.34%)
 2,24,41,64,76,049      instructions              #    0.26  insn per cycle         
                                                  #    3.52  stalled cycles per insn  (50.01%)
    8,84,30,79,219      branches                  #   20.643 M/sec                    (66.67%)
       1,04,85,342      branch-misses             #    0.12% of all branches          (83.34%)

     428.396804101 seconds time elapsed
       8534.611199      task-clock (msec)         #    1.000 CPUs utilized          
      39876.726670      task-clock (msec)         #    1.000 CPUs utilized          
                11      context-switches          #    0.000 K/sec                  
                11      cpu-migrations            #    0.000 K/sec                  
            12,334      page-faults               #    0.309 K/sec                  
 1,19,87,36,75,397      cycles                    #    3.006 GHz                      (83.33%)
      49,19,07,231      stalled-cycles-frontend   #    0.41% frontend cycles idle     (83.33%)
   50,40,53,90,525      stalled-cycles-backend    #   42.05% backend cycles idle      (33.35%)
 2,24,10,77,52,356      instructions              #    1.87  insn per cycle         
                                                  #    0.22  stalled cycles per insn  (50.01%)
    8,75,27,87,494      branches                  #  219.496 M/sec                    (66.68%)
         50,48,390      branch-misses             #    0.06% of all branches          (83.33%)

      39.879816492 seconds time elapsed
使用基于转置的乘法,“后端循环空闲”将如预期的那样大大减少。这是由于获取相干内存的等待时间较短。让我困惑的是,“页面错误”的数量是相同的。起初我认为这可能是一个上下文切换问题,所以我让程序运行时使用调度
SCHED_FIFO
和优先级
1
。上下文切换的数量从大约800个减少到11个,但“页面错误”仍然与以前完全相同

我使用的矩阵的维数是
2048x2048
,因此整个数组将无法容纳在4K页面中。它也不适合我的整个缓存(在我的例子中是4MiB),因为三个矩阵(3*2048*2048*sizeof(int)==48MiB)的大小远远超过了总的可用缓存。假设这里的“页面错误”指的是TLB未命中或缓存未命中,我看不出这两种算法如何具有完全相同的数字。我知道,我看到的许多效率改进来自一级缓存命中的事实,但这并不意味着RAM到缓存的传输没有作用

我还做了另一个实验,看看“页面错误”是否与数组大小成比例关系——正如预期的那样

所以我的问题是——

  • 假设“页面错误”指的是TLB未命中或缓存未命中,是否正确
  • 为什么两种算法的“页面错误”完全相同
  • 假设“页面错误”指的是TLB未命中或缓存未命中,是否正确

    否。当虚拟内存未映射到物理内存时,会发生页面错误。这有两个典型的原因:

  • 数据已从物理内存移动到磁盘(交换)。当页面错误发生时,数据将移回物理内存,并恢复虚拟内存中的映射
  • 一个内存区域被延迟分配。只有在第一次分配时,实际物理内存才会分配给相应的虚拟内存
  • 现在,页面错误可能只有在缓存未命中和TLB未命中之后才会发生,因为TLB只存储实际映射,而缓存只包含同样位于主内存中的数据

    下面是发生的情况的简化图表:

    阿拉文德·克里希纳(Aravind krishna)拍摄的图片,来自维基共享媒体

    为什么两种算法的“页面错误”完全相同

    您的所有数据都可以放入物理内存,因此您的案例中没有交换。这就给您留下了2),每个虚拟页面只发生一次。您使用48个MiB内存,它使用12288个4kib大小的页面。这对于两种算法都是一样的,并且几乎完全符合您所测量的内容

    1其他原因可能是内存映射IO或NUMA平衡


    2我想您可以构建一个体系结构,其中TLB包含未映射的虚拟地址信息,或者内存不包含缓存,但我怀疑这种体系结构是否存在。

    讨论了页面错误、TLB未命中和缓存未命中的区别。工作集的大小除以页面大小(4k)就相当于案例中的页面错误数。该算法与@Zulan没有任何区别。我不确定你为什么认为该算法的内存访问模式与页面错误无关-我的问题就是这个。好的,我将尝试为你的具体示例澄清。不幸的是,链接问题的答案有问题。为了减少页面错误,请为内核分配足够大的块以使用匿名hugepages。如果默认情况下没有将其设置为对物理内存进行碎片整理以查找连续的2M块,请使用
    madvise(MADV_HUGEPAGE)
    鼓励它对该区域进行碎片整理。此外,您还可以使用
    mmap(MAP\u POPULATE)
    将内存分配给“prefault”它,这样在触摸它时不会出现任何页面错误,只有TLB未命中@祖兰,你可能想在回答中提到这一点。