X86 与CPU微体系结构相关的奇怪现象

X86 与CPU微体系结构相关的奇怪现象,x86,cpu,performance-testing,intel,cpu-architecture,X86,Cpu,Performance Testing,Intel,Cpu Architecture,我正在做一个测试,通过指针测量一个函数调用的开销,下面是我的。然而,我发现了一些非常奇怪的事情,并寻求你的帮助 代码在VS2017的发布模式下编译,使用默认配置 共有4个测试平台,所有操作系统均为Win10。以下是一些详细信息: M1:CPU:i7-7700,微体系结构:卡比湖 M2:CPU:i7-7700,微体系结构:卡比湖 M3:CPU:i7-4790,微体系结构:Haswell M4:CPU:E5-2698 v3,微体系结构:Haswell 在下图中,图例的形式为机器参数\u顺序别名机

我正在做一个测试,通过指针测量一个函数调用的开销,下面是我的。然而,我发现了一些非常奇怪的事情,并寻求你的帮助

代码在VS2017的发布模式下编译,使用默认配置

共有4个测试平台,所有操作系统均为Win10。以下是一些详细信息:

  • M1:CPU:i7-7700,微体系结构:卡比湖
  • M2:CPU:i7-7700,微体系结构:卡比湖
  • M3:CPU:i7-4790,微体系结构:Haswell
  • M4:CPU:E5-2698 v3,微体系结构:Haswell
在下图中,图例的形式为
机器参数\u顺序别名
<上面列出了代码>机器<代码>参数\u顺序描述在一次运行期间传递给程序的
循环
的顺序<代码>别名表示该时间属于哪一部分
no exec
表示没有函数调用部分,也称为。第98-108行
exec
表示调用函数部分,也称为。第115-125行
per exec
是函数调用的成本。所有的时间单位都是毫秒<代码>每执行指的是左y轴,而其他代码则指的是右y轴

比较图1-4,您可以看到该图可能与CPU的微体系结构有关(M1和M2相似,M3和M4相似)

我的问题

  • 为什么所有机器都有两个阶段(
    LOOP<25
    LOOP>100
  • 为什么当
    32时,所有的无执行时间都有一个奇怪的峰值
    为什么所有机器都有两个阶段(循环<25和循环>100)

    当最里面的循环(j=0;j
    停止正确预测其退出时,会出现第一个不连续。在我的机器上,当
    循环
    达到24次迭代时,就会发生这种情况

    通过使用
    perf stat-I3000
    将基准测试输出与perf stats交错,您可以非常清楚地看到这一点:

    BenchWithFixture/RandomTarget/21     727779 ns     727224 ns       3851   78.6834M items/s
        45.003283831        2998.636997      task-clock (msec)                                           
        45.003283831                118      context-switches          #    0.039 K/sec                  
        45.003283831                  0      cpu-migrations            #    0.000 K/sec                  
        45.003283831                  0      page-faults               #    0.000 K/sec                  
        45.003283831      7,777,209,518      cycles                    #    2.595 GHz                    
        45.003283831     26,846,680,371      instructions              #    3.45  insn per cycle         
        45.003283831      6,711,087,432      branches                  # 2238.882 M/sec                  
        45.003283831          1,962,643      branch-misses             #    0.03% of all branches        
    BenchWithFixture/RandomTarget/22     751421 ns     750758 ns       3731   76.2169M items/s
        48.003487573        2998.943341      task-clock (msec)                                           
        48.003487573                111      context-switches          #    0.037 K/sec                  
        48.003487573                  0      cpu-migrations            #    0.000 K/sec                  
        48.003487573                  0      page-faults               #    0.000 K/sec                  
        48.003487573      7,778,285,186      cycles                    #    2.595 GHz                    
        48.003487573     26,956,175,646      instructions              #    3.47  insn per cycle         
        48.003487573      6,738,461,171      branches                  # 2247.947 M/sec                  
        48.003487573          1,973,024      branch-misses             #    0.03% of all branches        
    BenchWithFixture/RandomTarget/23     774490 ns     773955 ns       3620   73.9325M items/s
        51.003697814        2999.024360      task-clock (msec)                                           
        51.003697814                105      context-switches          #    0.035 K/sec                  
        51.003697814                  0      cpu-migrations            #    0.000 K/sec                  
        51.003697814                  0      page-faults               #    0.000 K/sec                  
        51.003697814      7,778,570,598      cycles                    #    2.595 GHz                    
        51.003697814     21,547,027,451      instructions              #    2.77  insn per cycle         
        51.003697814      5,386,175,806      branches                  # 1796.776 M/sec                  
        51.003697814         72,207,066      branch-misses             #    1.12% of all branches        
    BenchWithFixture/RandomTarget/24    1138919 ns    1138088 ns       2461   50.2777M items/s
        57.004129981        2999.003582      task-clock (msec)                                           
        57.004129981                108      context-switches          #    0.036 K/sec                  
        57.004129981                  0      cpu-migrations            #    0.000 K/sec                  
        57.004129981                  0      page-faults               #    0.000 K/sec                  
        57.004129981      7,778,509,575      cycles                    #    2.595 GHz                    
        57.004129981     19,061,717,197      instructions              #    2.45  insn per cycle         
        57.004129981      4,765,017,648      branches                  # 1589.492 M/sec                  
        57.004129981        103,398,285      branch-misses             #    1.65% of all branches        
    BenchWithFixture/RandomTarget/25    1171572 ns    1170748 ns       2391   48.8751M items/s
        60.004325775        2998.547350      task-clock (msec)                                           
        60.004325775                111      context-switches          #    0.037 K/sec                  
        60.004325775                  0      cpu-migrations            #    0.000 K/sec                  
        60.004325775                  0      page-faults               #    0.000 K/sec                  
        60.004325775      7,777,298,382      cycles                    #    2.594 GHz                    
        60.004325775     17,008,954,992      instructions              #    2.19  insn per cycle         
        60.004325775      4,251,656,734      branches                  # 1418.230 M/sec                  
        60.004325775        131,311,948      branch-misses             #    2.13% of all branches
    
    在过渡之前,分支预测失误率约为0.03%,然后在基准速度放缓或增加两个数量级时,分支预测失误率会跃升到2.13%左右。预测失误率实际上比您预期的要低一点:有25个分支(外加几个外部循环),您预期的预测失误率约为
    1/25==4%
    mispredicts,但我们没有看到,不确定原因

    在我的机器上,第一个循环(只有
    池[0](0,0,0,0,0)
    调用)与您的一样,在~24次
    循环
    迭代时没有转换,但我不清楚原因。我的经验是,TAGE计数器通常不能处理超过24ish周期的常量迭代循环,但是这里可能与间接分支预测器有一些交互作用。这很有趣


    为什么所有的无执行时间都有一个奇怪的峰值,当你说你想通过指针测量一个函数调用的成本时,但我不明白你是怎么做到的。您所说的
    无功能调用部分
    功能调用部分
    是什么意思?两者似乎都包含函数调用。这部分
    (d2-d1)/(1.0*规则*ITER)
    计算了什么?左y轴怎么可能是负的?循环的要点是什么?M1和M2之间的区别是什么?
    LOOP<25
    是现代Intel CPU可以正确预测短循环的循环退出分支的地方。服用20次后不服用一次比服用24次后不服用一次更容易。在我对简单嵌套循环的测试中,我发现内部的22到23次迭代(外部有数百万次迭代)是完美分支预测的截止点。你的文章似乎与代码不一致。你说“no exec意味着没有函数调用部分,也就是第98-108行。exec意味着调用函数部分,也就是第115-125行。”但就我所见,这两个定时循环要么涉及到一个函数调用(第一个循环)到固定位置
    池[0]
    ,要么涉及到两个函数调用,一个调用
    池[0]
    ,另一个调用
    池[t]
    对于t=1,2,3。。。等等。你说“perexec”是一个函数调用的值,所以它是另外两个测试中哪一个的循环规范化值?顺便说一句,我的印象是OP试图做的是测量一个(可能是随机的)间接调用的时间,该调用由一些其他工作参数化,可以与调用交错运行。我认为使用xor的关联性和交换性,编译器实际上可以将整个xor循环从所有循环中移出并计算一次,如果它知道循环没有逃逸函数的话。在我的测试中,它没有逃逸,但在OPs中,由于scanf,它逃逸了。不过编译器并没有那么聪明。@BeeOnRope:哦,对了,不是常数。但是对于加法来说,它并不像
    n*(n-1)/2那样简单,但只有9条指令长(),如果编译器花时间寻找这种非常罕见的模式,它将值得使用。(他们没有,也可能不应该!)
    
    BenchWithFixture/RandomTarget/21     727779 ns     727224 ns       3851   78.6834M items/s
        45.003283831        2998.636997      task-clock (msec)                                           
        45.003283831                118      context-switches          #    0.039 K/sec                  
        45.003283831                  0      cpu-migrations            #    0.000 K/sec                  
        45.003283831                  0      page-faults               #    0.000 K/sec                  
        45.003283831      7,777,209,518      cycles                    #    2.595 GHz                    
        45.003283831     26,846,680,371      instructions              #    3.45  insn per cycle         
        45.003283831      6,711,087,432      branches                  # 2238.882 M/sec                  
        45.003283831          1,962,643      branch-misses             #    0.03% of all branches        
    BenchWithFixture/RandomTarget/22     751421 ns     750758 ns       3731   76.2169M items/s
        48.003487573        2998.943341      task-clock (msec)                                           
        48.003487573                111      context-switches          #    0.037 K/sec                  
        48.003487573                  0      cpu-migrations            #    0.000 K/sec                  
        48.003487573                  0      page-faults               #    0.000 K/sec                  
        48.003487573      7,778,285,186      cycles                    #    2.595 GHz                    
        48.003487573     26,956,175,646      instructions              #    3.47  insn per cycle         
        48.003487573      6,738,461,171      branches                  # 2247.947 M/sec                  
        48.003487573          1,973,024      branch-misses             #    0.03% of all branches        
    BenchWithFixture/RandomTarget/23     774490 ns     773955 ns       3620   73.9325M items/s
        51.003697814        2999.024360      task-clock (msec)                                           
        51.003697814                105      context-switches          #    0.035 K/sec                  
        51.003697814                  0      cpu-migrations            #    0.000 K/sec                  
        51.003697814                  0      page-faults               #    0.000 K/sec                  
        51.003697814      7,778,570,598      cycles                    #    2.595 GHz                    
        51.003697814     21,547,027,451      instructions              #    2.77  insn per cycle         
        51.003697814      5,386,175,806      branches                  # 1796.776 M/sec                  
        51.003697814         72,207,066      branch-misses             #    1.12% of all branches        
    BenchWithFixture/RandomTarget/24    1138919 ns    1138088 ns       2461   50.2777M items/s
        57.004129981        2999.003582      task-clock (msec)                                           
        57.004129981                108      context-switches          #    0.036 K/sec                  
        57.004129981                  0      cpu-migrations            #    0.000 K/sec                  
        57.004129981                  0      page-faults               #    0.000 K/sec                  
        57.004129981      7,778,509,575      cycles                    #    2.595 GHz                    
        57.004129981     19,061,717,197      instructions              #    2.45  insn per cycle         
        57.004129981      4,765,017,648      branches                  # 1589.492 M/sec                  
        57.004129981        103,398,285      branch-misses             #    1.65% of all branches        
    BenchWithFixture/RandomTarget/25    1171572 ns    1170748 ns       2391   48.8751M items/s
        60.004325775        2998.547350      task-clock (msec)                                           
        60.004325775                111      context-switches          #    0.037 K/sec                  
        60.004325775                  0      cpu-migrations            #    0.000 K/sec                  
        60.004325775                  0      page-faults               #    0.000 K/sec                  
        60.004325775      7,777,298,382      cycles                    #    2.594 GHz                    
        60.004325775     17,008,954,992      instructions              #    2.19  insn per cycle         
        60.004325775      4,251,656,734      branches                  # 1418.230 M/sec                  
        60.004325775        131,311,948      branch-misses             #    2.13% of all branches