首发于旷视天元

借助 mperf 进行矩阵乘法极致优化

作者:旷视 MegEngine 架构师 洪超、实习生 南希

前言

单精度矩阵乘法(SGEMM)是非常典型的计算密集型算子,对 SGEMM 的优化也经常被当作算子优化从业人员的练手项目。本文将借助于 mperf,在 ARM A55 cpu 核心上对 SGEMM 的性能进行极致优化,过程中会展示 mperf辅助性能优化工作的基本逻辑。希望本文的读者对计算机体系结构有一定了解,并且可以补充一些 TMA 的基础概念。另外,关于本文使用的 mperf 工具,更多详细介绍请参见之前的文章 mperf 介绍

作为一个 C++ API 级别的工程,mperf 外部依赖少,可以简单方便(侵入式)集成到目标工程中,目前已经开源到 GitHub,欢迎大家试用交流。

本文需要优化的计算目标是 C=A*B,假设矩阵 A 大小为 M*K,矩阵 B 大小为 K*N,则得到矩阵 C 大小为 M*N。为了后文分块操作的方便,这里假设 M,N 是 4 的倍数,并选择 M=N=K 分别为 100,200,300,500,700,900 的矩阵尺寸,对不同优化版本进行性能测试。本文所有试验代码均在 mperf/apps/cpu_pmu_analysis 目录下。

矩阵乘法优化

寄存器和 FPU 优化——Naive 实现到循环展开

矩阵乘法的 Naive 实现为三层循环计算:

//lda:number of columns of A 
//ldb:number of columns of B
//ldc:number of columns of C 
#define A(i, j) a[(i)*lda + (j)]
#define B(i, j) b[(i)*ldb + (j)]
#define C(i, j) c[(i)*ldc + (j)]
void my_matmul_naive(int m, int n, int k, float* a, int lda, float* b, int ldb,
              float* c, int ldc) {
    int i, j, p;
    for (i = 0; i < m; i++) {         
        for (j = 0; j < n; j++) {     
            for (p = 0; p < k; p++) { 
                C(i, j) = C(i, j) + A(i, p) * B(p, j);
            }
        }
    }
}

此时,测试 M=N=K 分别为 100,200,300 的 mperf 性能数据见 Naive_mperf, 关于这些测试数据的简单介绍请参见 mperf 测试数据


测试命令(后文其他优化版本的测试命令不再重复贴出):

First, compile the testcase, using `/android_build.sh -m arm64-v8a`.
Then, copy build_dir/apps/arm_cpu_matmul_naive to your android platform, and run it.

从上面链接的 mperf 数据可以看到 Naive 实现的 GFLOPS 甚至不到 0.5,而 mperf 在 ARM A55 平台实测的峰值浮点算力可以达到 14GFLOPs,显然我们还有很长的路要走。

分析 TMA Level-1 的数据,也即比较 Frontend_Bound、Bad_Speculation、Backend_Bound 和 Retiring 的占比,可以发现占比最高的为 Backend_Bound,约为 50%,据此首先可以判断 Naive 版本的性能瓶颈位于处理器后端。进一步看 TMA Level-2 及以上级别的数据,发现 Backend_Bound 中占比最大的是 Core_Bound,而 Interlock_Bound 又占 Core_Bound 的 95% 以上,紧接着 Interlock_FPU 又几乎占 Interlock_Bound 的 100%。

由此可得,当前的瓶颈在于 Interlock_FPU,Interlock_FPU 占比大说明浮点计算触发了大量的 pipeline stall。除此之外,我们还观察到 Metric_Neon_Port_Util 为 0,这是因为 Naive 版本没有进行向量计算。

关于如何降低 Interlock_FPU,我们早期基于 mperf 做过验证,证明 unroll 可以有效降低 Interlock_FPU,过程如下:

#define UNROLL_RAW1(cb, v0, a...) \
    cb(0, ##a) 
#define UNROLL_RAW2(cb, v0, a...) \
    cb(0, ##a) cb(1, ##a) 
#define UNROLL_RAW5(cb, v0, a...) \
    cb(0, ##a) cb(1, ##a) cb(2, ##a) cb(3, ##a) cb(4, ##a)
#define UNROLL_RAW10(cb, v0, a...) \
    UNROLL_RAW5(cb, v0, ##a)       \
    cb(5, ##a) cb(6, ##a) cb(7, ##a) cb(8, ##a) cb(9, ##a)
#define UNROLL_RAW20(cb, v0, a...)                                          \
    UNROLL_RAW10(cb, v0, ##a)                                               \
    cb(10, ##a) cb(11, ##a) cb(12, ##a) cb(13, ##a) cb(14, ##a) cb(15, ##a) \
            cb(16, ##a) cb(17, ##a) cb(18, ##a) cb(19, ##a)
#define UNROLL_CALL0(step, cb, v...) UNROLL_RAW##step(cb, 0, ##v)
#define UNROLL_CALL(step, cb, v...) UNROLL_CALL0(step, cb, ##v)
#define THROUGHPUT(cb, func, UNROLL_NUM)                                    \
    static int func##_throughput_##UNROLL_NUM() {                           \
        asm volatile(                                                       \
        UNROLL_CALL(UNROLL_NUM, eor)                                        \
        "mov x0, %x[RUNS]\n"                                                \
        "1:\n"                                                              \
        UNROLL_CALL(UNROLL_NUM, cb)                                         \
        "subs  x0, x0, #1 \n"                                               \
        "bne 1b \n"                                                         \
        :                                                                   \
        : [RUNS] "r"(mperf::RUNS)                                           \
        : "cc", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "v9", \
          "v10", "v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18",    \
          "v19", "x0");                                                     \
        return mperf::RUNS * UNROLL_NUM;                                    \
    }
#define cb(i) "fmla v" #i ".4s, v" #i ".4s, v" #i ".4s\n"
THROUGHPUT(cb, fmla, 20)
THROUGHPUT(cb, fmla, 10)
THROUGHPUT(cb, fmla, 5)
THROUGHPUT(cb, fmla, 2)
THROUGHPUT(cb, fmla, 1)

在这个例子中,分别对不进行循环展开和以粒度为 2、5、10、20 的循环展开的 fmla 计算进行测试,结果如下:

UNROLL_NUM:1UNROLL_NUM:2UNROLL_NUM:5UNROLL_NUM:10UNROLL_NUM:20
Interlock_FPU : 0.49998Interlock_FPU : 0.25727Interlock_FPU : 0.02236Interlock_FPU : 0.02519Interlock_FPU : 0.02681
Metric_GFLOPs_Use : 3.98409Metric_GFLOPs_Use : 7.88556Metric_GFLOPs_Use : 12.97569Metric_GFLOPs_Use : 14.12275Metric_GFLOPs_Use : 14.74720

通过这个简单的例子我们可以看到,随着循环展开粒度的增加,Interlock_FPU 会逐渐降低,并逐渐趋于稳定。这是因为没有循环展开或循环展开特别小的时候,上一次循环还没有执行完成,下一次循环又要读取相同的寄存器,进而造成寄存器依赖。要消除寄存器依赖,首先要保证循环体中不同条指令使用不同的寄存器,并且尽量保证循环体内指令的条数大于该指令的 latency 和该指令的 throughput 的乘积。以本文在 a55 平台测试 fmla 向量计算为例,fmla 的 latency 为 4 个 cycle,并且 a55 处理器后端只有一个 port 可以执行fmla向量计算,也即 fmla 的 throughput 为 1,所以要求循环体 fmla 指令数大于 4 * 1 才可以解除寄存器依赖,这也符合上述试验结果的变化情况。

理解上面信息后,我们考虑在 Naive 版本上进行循环展开,并依据 Naive 版本 Metric_Neon_Port_Util 为 0,同时施加 SIMD 优化。具体做法是,先对前面的行列采用 8*12 展开,对剩余的列采用 8*4 展开,再对剩余的行先采用 4*12 展开,最后用 4*4 展开,期间配合ARM NEON指令进行向量化操作。

这里选择 8*12 是为了更充分的利用寄存器资源,是因为 ARM A55 上面有 32 个 128 bit 向量寄存器,以及考虑到本文最后 matmul 汇编版本的最内层实现大体如下(注意这里使用的外积计算矩阵乘,具体参见外积算矩阵乘):

  • 从 A 矩阵读 8 个 float 到 2 个向量寄存器,此时应该是 8 行里面每行的第一个数。
  • 从 B 矩阵读 12个float 到 3 个向量寄存器,应该是 12 列里每列的第一个数。
  • 用 fmla 指令,让 B 的每个 float 分别乘以 A 的两个向量寄存器,产生 24 个向量结果,也全部存储在寄存器中(24 个向量寄存器存储 8x12=96 个中间结果)。

采用 8*12 展开之后的代码结构如下:

void my_matmul_unroll(int m, int n, int k, float* a, int lda, float* b, int ldb,
                      float* c, int ldc) {
    int i, j;

    for (i = 0; i + 8 <= m; i += 8) {
        for (j = 0; j + 12 <= n; j += 12) {
            AddDot8x12(k, &A(i, 0), lda, &B(0, j), ldb, &C(i, j), ldc);
        }
        for (; j < n; j += 4) {
            AddDot8x4(k, &A(i, 0), lda, &B(0, j), ldb, &C(i, j), ldc);
        }
    }
    if (i != m) {
        for (j = 0; j + 12 <= n; j += 12) {
            AddDot4x12(k, &A(i, 0), lda, &B(0, j), ldb, &C(i, j), ldc);
        }
        for (; j < n; j += 4) {
            AddDot4x4(k, &A(i, 0), lda, &B(0, j), ldb, &C(i, j), ldc);
        }
    }
}

关于循环展开,可以用一个图来直观地理解,这里 mr=8,nr=12,我们每次用 A 矩阵的 8 * K 的小块和 B 矩阵的 K * 12 小块来计算 C 的一个 8 * 12 小块:

用 mperf 分析 unroll 版本的 matmul 实现,具体数据见 Unroll_mperf

对比 M,N,K 较小时(注: 在优化寄存器和 FPU 单元利用率的时候可以把问题规模先限制得比较小,减少访存相关 issue 的干扰),Unroll 版本与 Naive 版本的 Interlock_FPU、Metric_Neon_Port_Util 和 GFLOPS:

loopunrollloopunrollloopunroll
M=N=K=100M=N=K=100M=N=K=200M=N=K=200M=N=K=300M=N=K=300
Interlock_FPU : 0.41489Interlock_FPU : 0.11604Interlock_FPU : 0.39121Interlock_FPU : 0.11293Interlock_FPU : 0.34547Interlock_FPU : 0.11227
Metric_Neon_Port_Util : 0.00000Metric_Neon_Port_Util : 0.35740Metric_Neon_Port_Util : 0.00000Metric_Neon_Port_Util : 0.34510Metric_Neon_Port_Util : 0.00000Metric_Neon_Port_Util : 0.33232
Metric_GFLOPs_Use : 0.36511Metric_GFLOPs_Use : 5.73161Metric_GFLOPs_Use : 0.34685Metric_GFLOPs_Use : 5.50208Metric_GFLOPs_Use : 0.30557Metric_GFLOPs_Use : 5.24582

可以看到循环展开后可以看到 Interlock_FPU 占比下降明显,同时 Metric_Neon_Port_Util 明显上升,而 GFLOPS 指标有了数量级的提高,说明充分利用寄存器资源和提高 FPU 利用率有效提高了程序性能。

访存优化——分块和 PACK

上图是 Unroll 版本与 Naive 版本在不同矩阵尺寸下的性能对比,可以看到循环展开在矩阵尺寸比较小的情况下,性能提升还是很明显的,但是随着矩阵尺寸增大 unroll 的效果迅速下降。所以现在我们将注意力转移到,如何解决矩阵尺寸增大 GFLOPS 下降的问题。通过分析上节链接的 unroll 版本的 mperf 数据,可以看到,随着矩阵尺寸变大到一定程度,Memory_Bound 占比逐渐接近 50%,替代之前的 Interlock_FPU 成为新的性能瓶颈。而 Memory_Bound 占比高主要是 Load_Cache 造成的,这就指明了我们接下来需要进行访存相关的优化。

分块

之所以矩阵尺寸增加,unroll 版本的性能会下降,主要原因就是数据无法全部驻留在 Cache中,导致数据频繁地在 Cache 和主存之间换入换出,而处理器对主存的访问是非常昂贵的。为了减少对主存的重复访存,首先我们能想到的就是分块(Unroll 版本中提到的分块是内层分块,目的是优化寄存器和 FPU 的利用率,请注意区分),将分块之后的数据保存在 Cache 中,尽量使处理器发起的访存操作都能命中 cache 中的数据。

这里我们选择对 N,K 维分别进行 Nr 和 Kr 粒度的分块,结合循环展开部分的逻辑,整体的分块方式即为:外层选取 A 矩阵的 M*Kr 小块和 B 矩阵的 Kr*Nr 小块,内层再对这两个小块分别进行 mr 行和 nr 列的划分,所以最终内层每次计算 mr*Kr 的 A 小块和 Kr*nr 的 B 小块,得到 C 矩阵 mr*nr 小块的部分中间结果。

关于如何确定 Nr 和 Kr 的大小,我们的目标就是使得计算时需要用到的分块可以根据访存频繁的程度保存在 CPU 的各级存储中,原则就是访问越频繁的分块存储在速度越快的存储上,以及保证优先用满速度快的存储资源之后再下溢。针对 matmul, 具体约束条件设定为:

  • 将重复访存率最高的 mr*nr 大小的 C 小块保存在访存速度最快的寄存器上(unroll 版本就是这样假设的)。
  • 将下图中红色部分(包括计算完一个 mr*Nr 的 C 行块需要重复访问次数最多的 mr* Kr 的 A 行块,内层一次计算迭代需要用到的 Kr*nr 大小的 B 列块)都保存在 L1 中。
  • 由于计算完每一个 mr*Nr 的 C 行块,都需要重复遍历一次整个 Kr*Nr 大小的 B 块,因此希望将 Kr*Nr 大小的 B 块存放在 L2 中,使得每次读取 Kr*nr 的 B 列块的时候,都是从 L2 中读取。

依据上面的分配策略,并结合 CPU 中的各级存储资源(寄存器数量,L1D 和 L2)的尺寸,便可以确定最佳的 Nr,Kr 取值:

  • 可以根据 CPU 处理器的寄存器数量得到 mr 和 nr 的具体大小,寄存器容量 > mr*nr (unroll 版本就是遵循这个约束条件取的 mr=8,nr=12 )
  • 根据 L1D Cache 的大小结合 mr 和 nr 计算出 Kr,Kr=L1D/(mr+nr)
  • 再根据 L2 的大小计算出 B 矩阵中的 Nr,Nr=(L2-L1D)/Kr

在 ARM A55 上,最终得到的 Nr 为 252,Kr 为 256。注意:这里计算得到 Nr 为 256,但是由于我们选择 nr 为 12,因此为了避免不必要的余数处理,选择 Nr 为 12 的倍数简化问题。

Kr/Nr 分块的代码逻辑如下:

#define kc 256
#define nc 252
void my_mamtmul_block(int m, int n, int k, float *a, int lda, float *b, int ldb,
              float *c, int ldc) {
  int j, p, pb, ib;
  for (p = 0; p < k; p += kc) {
    pb = min(k - p, kc);
    for (j = 0; j < n; j += nc) {
      ib = min(n - j, nc);
      InnerKernel(m, ib, pb, &A(0, p), lda, &B(p, j), ldb, &C(0, j), ldc);
    }
  }
}

添加 Kr/Nr 分块后的 mperf 性能数据见 Block_mperf

对比 Kr/Nr 分块前后以下变化明显的数据:

unrollblockunrollblock
M=N=K=700M=N=K=700M=N=K=900M=N=K=900
Memory_Bound : 0.31008Memory_Bound : 0.23551Memory_Bound : 0.48435Memory_Bound : 0.25875
Load_Bound : 0.31003Load_Bound : 0.23547Load_Bound : 0.48433Load_Bound : 0.25870
Load_DTLB : 0.01087Load_DTLB : 0.01252Load_DTLB : 0.01226Load_DTLB : 0.02023
Load_Cache : 0.30802Load_Cache : 0.21025Load_Cache : 0.45685Load_Cache : 0.23244
Store_Bound : 0.00005Store_Bound : 0.00004Store_Bound : 0.00002Store_Bound : 0.00005
Store_TLB : 0.00003Store_TLB : 0.00010Store_TLB : 0.00002Store_TLB : 0.00004
Store_Buffer : 0.00001Store_Buffer : 0.00001Store_Buffer : 0.00000Store_Buffer : 0.00001
Metric_L1D_Miss_Ratio : 0.03458Metric_L1D_Miss_Ratio : 0.01878Metric_L1D_Miss_Ratio : 0.03515Metric_L1D_Miss_Ratio : 0.02113
Metric_L1D_RD_Miss_Ratio : 0.03581Metric_L1D_RD_Miss_Ratio : 0.02030Metric_L1D_RD_Miss_Ratio : 0.03639Metric_L1D_RD_Miss_Ratio : 0.02284
Metric_L1D_WR_Miss_Ratio : 0.00379Metric_L1D_WR_Miss_Ratio : 0.00169Metric_L1D_WR_Miss_Ratio : 0.00390Metric_L1D_WR_Miss_Ratio : 0.00189
Metric_L2D_Miss_Ratio : 0.15673Metric_L2D_Miss_Ratio : 0.26215Metric_L2D_Miss_Ratio : 0.18801Metric_L2D_Miss_Ratio : 0.23144
Metric_L2D_RD_Miss_Ratio : 0.31396Metric_L2D_RD_Miss_Ratio : 0.52642Metric_L2D_RD_Miss_Ratio : 0.37706Metric_L2D_RD_Miss_Ratio : 0.46396
Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000
Metric_L3D_Miss_Ratio : 0.18870Metric_L3D_Miss_Ratio : 0.05405Metric_L3D_Miss_Ratio : 0.23623Metric_L3D_Miss_Ratio : 0.05183
Metric_L3D_RD_Miss_Ratio : 0.38055Metric_L3D_RD_Miss_Ratio : 0.10890Metric_L3D_RD_Miss_Ratio : 0.47494Metric_L3D_RD_Miss_Ratio : 0.10425
Metric_Load_Port_Util : 0.12046Metric_Load_Port_Util : 0.13779Metric_Load_Port_Util : 0.09069Metric_Load_Port_Util : 0.13191
Metric_Store_Port_Util : 0.07090Metric_Store_Port_Util : 0.08126Metric_Store_Port_Util : 0.05370Metric_Store_Port_Util : 0.07829
Metric_GFLOPs_Use : 3.95044Metric_GFLOPs_Use : 4.53463Metric_GFLOPs_Use : 3.03964Metric_GFLOPs_Use : 4.37174

Kr/Nr 分块后可以看到在矩阵较大时进行快速矩阵乘法,GFLOPS 确实上升不少,Load_Cache 和 Metric_L3D_RD_Miss_Ratio 等均有明显下降。这说明 Kr/Nr 分块确实大幅减少了对 latency 非常大的系统主存的访问,优化了程序的访存性能。

数据 PACK

分析 Kr/Nr 分块后测得的 mperf 数据,可以看到随着矩阵尺寸变大,性能也能保持相对稳定,没有明显下降。但是此时 mperf 拿到的 TMA 指标显示,Backend_Bound 中的 Memory_Bound 占比依旧很高,性能瓶颈还是停留在访存部分。

进一步思考,在计算 mr*nr 大小的 C 小块的时候,每一次迭代都需要读取 A 矩阵 mr*1 的数据,而本文测试的矩阵数据都是行主序,即不同行相同列的数据是内存不连续的,访存不连续就意味着对 Cache 不友好。同样在不同次迭代中,需要读取矩阵 B 中不同行的 1*nr 小块的数据,自然也存在数据读取不连续的情况。考虑到在分块计算 matmul 的逻辑下,A 的所有行块和 B 中的所有列块将被读取多次,因此可以通过对 A 和 B 提前进行数据 PACK,这样只在第一次 PACK 时候对 Cache 不友好,而后面计算的时候多次访问数据均为连续访存,因此收益巨大。
下图说明了对 A/B 矩阵分别 PACK 的过程:

void InnerKernel(int m, int n, int k, float* a, int lda, float* b, int ldb,
                 float* c, int ldc) {
    int i, j;
    float packedA[m * k];
    float packedB[k * n];

    for (i = 0; i + 8 <= m; i += 8) {
        PackMatrixA_8(k, &A(i, 0), lda, packedA + i * k);
        for (j = 0; j + 12 <= n; j += 12) {
            if (0 == i) {
                PackMatrixB_12(k, &B(0, j), ldb, packedB + j * k);
            }
            AddDot8x12(k, packedA + i * k, k, packedB + j * k, 12, &C(i, j),
                       ldc);
        }
        for (; j < n; j += 4) {
            if (0 == i) {
                PackMatrixB_4(k, &B(0, j), ldb, packedB + j * k);
            }
            AddDot8x4(k, packedA + i * k, k, packedB + j * k, 12, &C(i, j),
                      ldc);
        }
    }
    if (i != m) {
        PackMatrixA_4(k, &A(i, 0), lda, packedA + i * k);
        for (j = 0; j + 12 <= n; j += 12) {
            AddDot4x12(k, packedA + i * k, k, packedB + j * k, 12, &C(i, j),
                       ldc);
        }
        for (; j < n; j += 4) {
            AddDot4x4(k, packedA + i * k, k, packedB + j * k, 12, &C(i, j),
                      ldc);
        }
    }
}

PACK 后的 mperf 性能数据见 Pack_mperf

对比PACK前后的数据:

blockpackblockpackblockpack
M=N=K=100M=N=K=100M=N=K=200M=N=K=200M=N=K=300M=N=K=300
Load_Cache : 0.04850Load_Cache : 0.03037Load_Cache : 0.05591Load_Cache : 0.01925Load_Cache : 0.09417Load_Cache : 0.05596
Interlock_FPU : 0.09043Interlock_FPU : 0.34918Interlock_FPU : 0.08863Interlock_FPU : 0.37332Interlock_FPU : 0.08732Interlock_FPU : 0.36597
Metric_L1D_TLB_Miss_Ratio : 0.00090Metric_L1D_TLB_Miss_Ratio : 0.00224Metric_L1D_TLB_Miss_Ratio : 0.00483Metric_L1D_TLB_Miss_Ratio : 0.00235Metric_L1D_TLB_Miss_Ratio : 0.00685Metric_L1D_TLB_Miss_Ratio : 0.00294
Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00001Metric_L2_TLB_Miss_Ratio : 0.00013Metric_L2_TLB_Miss_Ratio : 0.00001Metric_L2_TLB_Miss_Ratio : 0.00072
L2D_TLB_REFILL 0.000000L2D_TLB_REFILL 0.000000L2D_TLB_REFILL 0.200000L2D_TLB_REFILL 0.700000L2D_TLB_REFILL 1.200000L2D_TLB_REFILL 10.800000
L2D_TLB 910.400024L2D_TLB 822.400024L2D_TLB 23194.500000L2D_TLB 5456.500000L2D_TLB 97020.296875L2D_TLB 15094.200195
Metric_GFLOPs_Use : 6.34394Metric_GFLOPs_Use : 7.00634Metric_GFLOPs_Use : 6.24761Metric_GFLOPs_Use : 7.27444Metric_GFLOPs_Use : 5.86449Metric_GFLOPs_Use : 6.94621
blockpackblockpackblockpack
M=N=K=500M=N=K=500M=N=K=700M=N=K=700M=N=K=900M=N=K=900
Load_Cache : 0.16088Load_Cache : 0.11704Load_Cache : 0.20015Load_Cache : 0.20065Load_Cache : 0.23572Load_Cache : 0.22885
Interlock_FPU : 0.07988Interlock_FPU : 0.34384Interlock_FPU : 0.07642Interlock_FPU : 0.31200Interlock_FPU : 0.07156Interlock_FPU : 0.30176
Metric_L1D_TLB_Miss_Ratio : 0.01143Metric_L1D_TLB_Miss_Ratio : 0.00328Metric_L1D_TLB_Miss_Ratio : 0.01573Metric_L1D_TLB_Miss_Ratio : 0.00413Metric_L1D_TLB_Miss_Ratio : 0.01915Metric_L1D_TLB_Miss_Ratio : 0.00511
Metric_L2_TLB_Miss_Ratio : 0.00048Metric_L2_TLB_Miss_Ratio : 0.01302Metric_L2_TLB_Miss_Ratio : 0.02578Metric_L2_TLB_Miss_Ratio : 0.07241Metric_L2_TLB_Miss_Ratio : 0.06266Metric_L2_TLB_Miss_Ratio : 0.26738
L2D_TLB_REFILL 358.600006L2D_TLB_REFILL 956.500000L2D_TLB_REFILL 72607.601562L2D_TLB_REFILL 16910.800781L2D_TLB_REFILL 460042.187500L2D_TLB_REFILL 157443.500000
L2D_TLB 744285.812500L2D_TLB 73438.000000L2D_TLB 2816898.500000L2D_TLB 233527.500000L2D_TLB 7341533.500000L2D_TLB 588828.312500
Metric_GFLOPs_Use : 5.53592Metric_GFLOPs_Use : 6.66007Metric_GFLOPs_Use : 5.10062Metric_GFLOPs_Use : 5.91676Metric_GFLOPs_Use : 4.89490Metric_GFLOPs_Use : 5.65741

可以看到进行 PACK 优化后 GFLOPS 又有一定幅度的增长。此时可以观察到 L1D_TLB_Miss_Ratio 有所降低,并且在 M=N=K >= 700 时 L2D_TLB_REFILL 明显降低,说明 PACK 确实可以通过减少缺页的发生,减少 TLB miss, 从而提升性能。

pipeline 优化——嵌入汇编

分析 PACK 之后的 mperf 数据,可以发现 Backend_Bound 占比 40% 以上,其中 Core_Bound 类别下的 Interlock_FPU 再次成为性能瓶颈。回想 unroll 版本减少 Interlock_FPU 的思路,是通过循环展开给编译器更大的优化空间,让编译器充分利用寄存器来减少流水线依赖,但编译器也是有局限的。一般来说,编译器考虑到通用性,是很难生成针对特定处理器架构特点的最优汇编实现的(ARM in-order 架构的小核上更是如此)。因此下一步的想法就是优化编译器生成的汇编,通过把内层计算逻辑替换为嵌入式汇编,依据架构特性调整指令选择和指令排布,进一步减少 pipeline 上的依赖和冲突,从而达成降低 Interlock_FPU 的目的。

首先,我们对比了 PACK 版本的 mperf 数据中的 FPU_util 和纯算力测试情况下的 FPU_util,发现 PACK 版本的 FPU_util 相对低了很多。也就是说,PACK 版本的 matmul 对处理器 SIMD 单元的利用率还是有一定提升空间的(下这个判断的一个前提也是考虑到前文已经对 matmul 访存部分优化得很充分了,并且考虑到内层循环中没有分支判断等复杂逻辑,只是比较存粹的访存和计算指令的 interleave。换句话说,汇编优化一般是留到最后进行的)。

其次,我们注意到编译器生成的汇编代码中,数据加载使用的是 ldq 指令(ldq 指的是 armv8 isa 中 128bit load 操作),但是结合上面 FPU_util 数值比理想情况低的观察(会关注 ldq 指令,是因为我们了解到 ARM A55 的访存能力弱,一个 cycle 最多 load 64bit,store 128bit),我们有理由怀疑 ldq 指令的选择可能会造成 pipeline stall。通过查询 ARM A55 trm 手册,我们发现 ldq 在 a55 上需要两个 cycle 才能 issue 出去,并且 ldq 跟 fmla 不能双发射(注:ARM A55 是双发射架构),这就证实了 ldq 会造成计算和访存指令无法双发射,并造成 Metric_FPU_util 数值的下降。进一步,我们发现 ldr,ldx,ins 三种指令都能与 fmla 双发射,且发射周期都是 1 个 cycle,而这三条指令可以组合出 ldq 等价的操作。因此,我们使用 ldr,ldx,ins 指令组合来替换 ldq 指令,就可以提高流水线的满载程度,进而提高性能。

我们用一个小的测试例子来进行验证: 考虑下面两段代码: 优化前,使用 ldq 指令加载数据,代码如下:

asm volatile(
                "fmla v1.4s, v1.4s, v1.s[0]\n"
                "ld1 {v0.4s}, [%[b_ptr]]\n"
                "fmla v2.4s, v2.4s, v2.s[0]\n"
                "ld1 {v7.4s}, [%[b_ptr]]\n"
                "fmla v3.4s, v3.4s, v3.s[0]\n"
                "fmla v4.4s, v4.4s, v4.s[0]\n"
                "fmla v5.4s, v5.4s, v5.s[0]\n"
                "fmla v6.4s, v6.4s, v6.s[0]\n"
                : [b_ptr] "+r"(b_ptr)
                :
                : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7");

优化后,将 ldq 拆分为 ldr,ldx,ins 指令加载数据,代码如下:

asm volatile(
               "fmla v1.4s, v1.4s, v1.s[0]\n"
               "ldr d0, [%[b_ptr]]\n"
               "fmla v2.4s, v2.4s, v2.s[0]\n"
               "ldr x0, [%[b_ptr], #8]\n"
               "fmla v3.4s, v3.4s, v3.s[0]\n"
               "ins v0.d[1], x0\n"
               "fmla v4.4s, v4.4s, v4.s[0]\n"
               "ldr d7, [%[b_ptr]]\n"
               "fmla v5.4s, v5.4s, v5.s[0]\n"
               "ldr x0, [%[b_ptr], #8]\n"
               "fmla v6.4s, v6.4s, v6.s[0]\n"
               "ins v7.d[1], x0\n"
               : [b_ptr] "+r"(b_ptr)
               :
               : "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7");

我们对优化前和优化后的版本进行测试,对分析 mperf 拿到的数据,看到主要的变化为:

ldqldr+ldr+ins
Metric_Load_Port_Util : 0.39650Metric_Load_Port_Util : 0.69312
Metric_GFLOPs_Use : 5.00572Metric_GFLOPs_Use : 7.70664

可以看到 Metric_Load_Port_Util 和 Metric_GFLOPs_Use 均提升明显,也就验证了前面的猜想。

因此,在嵌入的汇编代码中,我们应用上面提到的加载指令的替换,测得的 mperf 性能数据见:ASM_mperf

对比分析 PACK 和 ASM 两个版本的 mperf 数据,可以看到 Metric_Neon_Port_Util 和 Metric_Load_Port_Util 均显著上升。

PACKASMPACKASMPACKASM
M=N=K=200M=N=K=200M=N=K=300M=N=K=300M=N=K=500M=N=K=500
Bad_Speculation : 0.29156Bad_Speculation : 0.13931Bad_Speculation : 0.27964Bad_Speculation : 0.10896Bad_Speculation : 0.26751Bad_Speculation : 0.02394
Branch_Mispredicts : 530.09998Branch_Mispredicts : 516.29999Branch_Mispredicts : 1718.09998Branch_Mispredicts : 1237.50000Branch_Mispredicts : 7551.70020Branch_Mispredicts : 6101.39990
Load_Cache : 0.01824Load_Cache : 0.02975Load_Cache : 0.05483Load_Cache : 0.10898Load_Cache : 0.10329Load_Cache : 0.25344
Interlock_FPU : 0.37414Interlock_FPU : 0.00000Interlock_FPU : 0.36819Interlock_FPU : 0.00000Interlock_FPU : 0.34176Interlock_FPU : 0.00000
Retiring : 0.30317Retiring : 0.79307Retiring : 0.28769Retiring : 0.74938Retiring : 0.26564Retiring : 0.64852
LD_Retiring : 0.04036LD_Retiring : 0.21852LD_Retiring : 0.03691LD_Retiring : 0.20725LD_Retiring : 0.03349LD_Retiring : 0.17772
ST_Retiring : 0.00510ST_Retiring : 0.01946ST_Retiring : 0.00493ST_Retiring : 0.01859ST_Retiring : 0.00279ST_Retiring : 0.00998
DP_Retiring : 0.02283DP_Retiring : 0.03734DP_Retiring : 0.02146DP_Retiring : 0.03561DP_Retiring : 0.01926DP_Retiring : 0.02792
ASE_Retiring : 0.22917ASE_Retiring : 0.42233ASE_Retiring : 0.21917ASE_Retiring : 0.39544ASE_Retiring : 0.20533ASE_Retiring : 0.35224
VFP_Retiring : 0.22917VFP_Retiring : 0.42233VFP_Retiring : 0.21917VFP_Retiring : 0.39544VFP_Retiring : 0.20533VFP_Retiring : 0.35224
Metric_Load_Port_Util : 0.08072Metric_Load_Port_Util : 0.43704Metric_Load_Port_Util : 0.07381Metric_Load_Port_Util : 0.41450Metric_Load_Port_Util : 0.06698Metric_Load_Port_Util : 0.35545
Metric_Neon_Port_Util : 0.45834Metric_Neon_Port_Util : 0.84466Metric_Neon_Port_Util : 0.43834Metric_Neon_Port_Util : 0.79088Metric_Neon_Port_Util : 0.41067Metric_Neon_Port_Util : 0.70447
Metric_GFLOPs_Use : 7.27027Metric_GFLOPs_Use : 13.45224Metric_GFLOPs_Use : 6.96883Metric_GFLOPs_Use : 12.57732Metric_GFLOPs_Use : 6.63430Metric_GFLOPs_Use : 10.50762
PACKASMPACKASM
M=N=K=700M=N=K=700M=N=K=900M=N=K=900
Bad_Speculation : 0.24406Bad_Speculation : 0.07470Bad_Speculation : 0.22907Bad_Speculation : 0.06565
Branch_Mispredicts : 22910.50000Branch_Mispredicts : 17442.59961Branch_Mispredicts : 50927.00000Branch_Mispredicts : 37761.50000
Load_Cache : 0.20224Load_Cache : 0.38846Load_Cache : 0.21719Load_Cache : 0.42574
Interlock_FPU : 0.31210Interlock_FPU : 0.00000Interlock_FPU : 0.30707Interlock_FPU : 0.00000
Retiring : 0.23871Retiring : 0.50446Retiring : 0.23278Retiring : 0.47370
LD_Retiring : 0.02966LD_Retiring : 0.13824LD_Retiring : 0.02869LD_Retiring : 0.12980
ST_Retiring : 0.00241ST_Retiring : 0.00750ST_Retiring : 0.00230ST_Retiring : 0.00690
DP_Retiring : 0.01710DP_Retiring : 0.02162DP_Retiring : 0.01657DP_Retiring : 0.02026
ASE_Retiring : 0.18532ASE_Retiring : 0.27398ASE_Retiring : 0.18116ASE_Retiring : 0.25727
VFP_Retiring : 0.18532VFP_Retiring : 0.27398VFP_Retiring : 0.18116VFP_Retiring : 0.25727
Metric_Load_Port_Util : 0.05932Metric_Load_Port_Util : 0.27647Metric_Load_Port_Util : 0.05737Metric_Load_Port_Util : 0.25961
Metric_Neon_Port_Util : 0.37064Metric_Neon_Port_Util : 0.54795Metric_Neon_Port_Util : 0.36232Metric_Neon_Port_Util : 0.51453
Metric_GFLOPs_Use : 5.88770Metric_GFLOPs_Use : 8.73145Metric_GFLOPs_Use : 5.75827Metric_GFLOPs_Use : 8.13339

注意到完成汇编优化后,在矩阵大小 M,N,K <= 300 时,GFLOPS 性能已经达到峰值算力的 90% 以上,基本上可以判定较小尺寸的情况下,matmul 在 ARM A55 平台上已经优化到位了。而当 M,N,K 比较大时,依旧有进一步的优化空间。但是考虑到本文的主要目的,是借助 matmul 优化来说明 mperf 可以给性能优化工作带来哪些助益,所以就不继续进一步的优化关工作了。

总结

本文以 ARM A55 平台上的矩阵乘优化为例,详细介绍了如何用 mperf 分析当前实现的性能表现,找到性能瓶颈,进而确定下一步的优化方向,如此反复迭代,最终取得了接近硬件性能峰值的性能表现。本文各个版本 matmul 的性能对比,见下图:

附录

mperf 测试数据

这里贴了不同优化版本的 mperf 测试数据,每一个版本下的测试数据都包含两部分:一部分是非 Metric 前缀命名的,都是 TMA 范式下的指标;另一部分是 Metric 前缀命名的则是非 TMA 范式下,但是对性能优化有辅助作用的指标。这两类指标都是基于 PMU 原始 event 四则运算加工得到的,具体的计算公式请参见 ARM a55 tma

另,TMA 范式下的指标呈现多级展开的关系,由于当前 mperf 未提供可视化工具,请参考下图示意的层级关系进行对号入座。并且,请注意附录贴的 TMA 数值均为无量纲百分比。

Naive_mperf

M=N=K=100M=N=K=200M=N=K=300
Frontend_Bound : 0.00319Frontend_Bound : 0.00149Frontend_Bound : 0.00088
Fetch_Latency : 0.00319Fetch_Latency : 0.00149Fetch_Latency : 0.00088
ICache_Misses : 0.00004ICache_Misses : 0.00001ICache_Misses : 0.00001
ITLB_Misses : 0.00000ITLB_Misses : 0.00001ITLB_Misses : 0.00000
Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000
Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000
Bad_Speculation : 0.16147Bad_Speculation : 0.14928Bad_Speculation : 0.13111
Branch_Mispredicts : 10112.59961Branch_Mispredicts : 40262.80078Branch_Mispredicts : 90512.79688
Backend_Bound : 0.46695Backend_Bound : 0.50441Backend_Bound : 0.56425
Memory_Bound : 0.04070Memory_Bound : 0.08765Memory_Bound : 0.18501
Load_Bound : 0.04054Load_Bound : 0.08667Load_Bound : 0.18443
Load_DTLB : 0.00002Load_DTLB : 0.03964Load_DTLB : 0.05109
Load_Cache : 0.04006Load_Cache : 0.04649Load_Cache : 0.13333
Store_Bound : 0.00016Store_Bound : 0.00098Store_Bound : 0.00058
Store_TLB : 0.00000Store_TLB : 0.00098Store_TLB : 0.00058
Store_Buffer : 0.00017Store_Buffer : 0.00000Store_Buffer : 0.00000
Core_Bound : 0.42625Core_Bound : 0.41676Core_Bound : 0.37925
Interlock_Bound : 0.41492Interlock_Bound : 0.39122Interlock_Bound : 0.34547
Interlock_AGU : 0.00001Interlock_AGU : 0.00000Interlock_AGU : 0.00000
Interlock_FPU : 0.41489Interlock_FPU : 0.39121Interlock_FPU : 0.34547
Core_Bound_Others : 0.01133Core_Bound_Others : 0.02555Core_Bound_Others : 0.03378
Retiring : 0.36839Retiring : 0.34483Retiring : 0.30376
LD_Retiring : 0.10529LD_Retiring : 0.09854LD_Retiring : 0.08680
ST_Retiring : 0.00055ST_Retiring : 0.00026ST_Retiring : 0.00015
DP_Retiring : 0.10854DP_Retiring : 0.10006DP_Retiring : 0.08769
ASE_Retiring : 0.00000ASE_Retiring : 0.00000ASE_Retiring : 0.00000
VFP_Retiring : 0.10372VFP_Retiring : 0.09780VFP_Retiring : 0.08637
PC_Write_Retiring : 0.05242PC_Write_Retiring : 0.04916PC_Write_Retiring : 0.04334
BR_IMMED_Retiring : 0.05242BR_IMMED_Retiring : 0.04916BR_IMMED_Retiring : 0.04334
BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000
BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000
Metric_L1D_Miss_Ratio : 0.05678Metric_L1D_Miss_Ratio : 0.02601Metric_L1D_Miss_Ratio : 0.06416
Metric_L1D_RD_Miss_Ratio : 0.05673Metric_L1D_RD_Miss_Ratio : 0.02592Metric_L1D_RD_Miss_Ratio : 0.06405
Metric_L1D_WR_Miss_Ratio : 0.17102Metric_L1D_WR_Miss_Ratio : 0.18698Metric_L1D_WR_Miss_Ratio : 0.33719
Metric_L2D_Miss_Ratio : 0.00473Metric_L2D_Miss_Ratio : 0.14580Metric_L2D_Miss_Ratio : 0.23731
Metric_L2D_RD_Miss_Ratio : 0.01038Metric_L2D_RD_Miss_Ratio : 0.29075Metric_L2D_RD_Miss_Ratio : 0.47490
Metric_L2D_WR_Miss_Ratio : 0.00116Metric_L2D_WR_Miss_Ratio : 0.00014Metric_L2D_WR_Miss_Ratio : 0.00004
Metric_L3D_Miss_Ratio : 0.00158Metric_L3D_Miss_Ratio : 0.00038Metric_L3D_Miss_Ratio : 0.00027
Metric_L3D_RD_Miss_Ratio : 0.00399Metric_L3D_RD_Miss_Ratio : 0.00077Metric_L3D_RD_Miss_Ratio : 0.00054
Metric_BR_Mispred_Ratio : 0.01000Metric_BR_Mispred_Ratio : 0.00501Metric_BR_Mispred_Ratio : 0.00334
Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000
Metric_L1D_TLB_Miss_Ratio : 0.00007Metric_L1D_TLB_Miss_Ratio : 0.10279Metric_L1D_TLB_Miss_Ratio : 0.15008
Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00000
Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000
Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000
Metric_Load_Port_Util : 0.21057Metric_Load_Port_Util : 0.19708Metric_Load_Port_Util : 0.17360
Metric_Store_Port_Util : 0.00110Metric_Store_Port_Util : 0.00052Metric_Store_Port_Util : 0.00031
Metric_Neon_Port_Util : 0.00000Metric_Neon_Port_Util : 0.00000Metric_Neon_Port_Util : 0.00000
Metric_GFLOPs_Use : 0.36511Metric_GFLOPs_Use : 0.34685Metric_GFLOPs_Use : 0.30557

Unroll_mperf

M=N=K=100M=N=K=200M=N=K=300M=N=K=500M=N=K=700M=N=K=900
Frontend_Bound : 0.00074Frontend_Bound : 0.00016Frontend_Bound : 0.00010Frontend_Bound : 0.00007Frontend_Bound : 0.00008Frontend_Bound : 0.00006
Fetch_Latency : 0.00074Fetch_Latency : 0.00016Fetch_Latency : 0.00010Fetch_Latency : 0.00007Fetch_Latency : 0.00008Fetch_Latency : 0.00006
ICache_Misses : 0.00034ICache_Misses : 0.00004ICache_Misses : 0.00003ICache_Misses : 0.00003ICache_Misses : 0.00004ICache_Misses : 0.00004
ITLB_Misses : 0.00000ITLB_Misses : 0.00000ITLB_Misses : 0.00000ITLB_Misses : 0.00004ITLB_Misses : 0.00001ITLB_Misses : 0.00001
Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000
Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000
Bad_Speculation : 0.47808Bad_Speculation : 0.46884Bad_Speculation : 0.44958Bad_Speculation : 0.43876Bad_Speculation : 0.34968Bad_Speculation : 0.27817
Branch_Mispredicts : 134.60001Branch_Mispredicts : 472.39999Branch_Mispredicts : 1017.79999Branch_Mispredicts : 2919.89990Branch_Mispredicts : 5817.79980Branch_Mispredicts : 10082.20020
Backend_Bound : 0.18936Backend_Bound : 0.20947Backend_Bound : 0.24190Backend_Bound : 0.26918Backend_Bound : 0.41795Backend_Bound : 0.54684
Memory_Bound : 0.04723Memory_Bound : 0.07794Memory_Bound : 0.10863Memory_Bound : 0.14413Memory_Bound : 0.31008Memory_Bound : 0.48435
Load_Bound : 0.04660Load_Bound : 0.07781Load_Bound : 0.10861Load_Bound : 0.14411Load_Bound : 0.31003Load_Bound : 0.48433
Load_DTLB : 0.00056Load_DTLB : 0.00293Load_DTLB : 0.00382Load_DTLB : 0.00629Load_DTLB : 0.01087Load_DTLB : 0.01226
Load_Cache : 0.04502Load_Cache : 0.06666Load_Cache : 0.09210Load_Cache : 0.12851Load_Cache : 0.30802Load_Cache : 0.45685
Store_Bound : 0.00063Store_Bound : 0.00013Store_Bound : 0.00002Store_Bound : 0.00002Store_Bound : 0.00005Store_Bound : 0.00002
Store_TLB : 0.00001Store_TLB : 0.00001Store_TLB : 0.00001Store_TLB : 0.00001Store_TLB : 0.00003Store_TLB : 0.00002
Store_Buffer : 0.00051Store_Buffer : 0.00011Store_Buffer : 0.00001Store_Buffer : 0.00001Store_Buffer : 0.00001Store_Buffer : 0.00000
Core_Bound : 0.14213Core_Bound : 0.13153Core_Bound : 0.13327Core_Bound : 0.12505Core_Bound : 0.10787Core_Bound : 0.06249
Interlock_Bound : 0.11653Interlock_Bound : 0.11316Interlock_Bound : 0.11241Interlock_Bound : 0.10508Interlock_Bound : 0.08437Interlock_Bound : 0.06386
Interlock_AGU : 0.00033Interlock_AGU : 0.00016Interlock_AGU : 0.00010Interlock_AGU : 0.00006Interlock_AGU : 0.00003Interlock_AGU : 0.00002
Interlock_FPU : 0.11604Interlock_FPU : 0.11293Interlock_FPU : 0.11227Interlock_FPU : 0.10500Interlock_FPU : 0.08432Interlock_FPU : 0.06384
Core_Bound_Others : 0.02560Core_Bound_Others : 0.01837Core_Bound_Others : 0.02086Core_Bound_Others : 0.01997Core_Bound_Others : 0.02350Core_Bound_Others : -0.00137
Retiring : 0.33182Retiring : 0.32153Retiring : 0.30842Retiring : 0.29199Retiring : 0.23229Retiring : 0.17493
LD_Retiring : 0.08541LD_Retiring : 0.08371LD_Retiring : 0.07969LD_Retiring : 0.07575LD_Retiring : 0.06023LD_Retiring : 0.04534
ST_Retiring : 0.04820ST_Retiring : 0.04789ST_Retiring : 0.04711ST_Retiring : 0.04411ST_Retiring : 0.03545ST_Retiring : 0.02685
DP_Retiring : 0.01584DP_Retiring : 0.01401DP_Retiring : 0.01244DP_Retiring : 0.01195DP_Retiring : 0.00923DP_Retiring : 0.00684
ASE_Retiring : 0.17870ASE_Retiring : 0.17255ASE_Retiring : 0.16616ASE_Retiring : 0.15724ASE_Retiring : 0.12510ASE_Retiring : 0.09421
VFP_Retiring : 0.17870VFP_Retiring : 0.17255VFP_Retiring : 0.16616VFP_Retiring : 0.15724VFP_Retiring : 0.12510VFP_Retiring : 0.09421
PC_Write_Retiring : 0.00395PC_Write_Retiring : 0.00350PC_Write_Retiring : 0.00310PC_Write_Retiring : 0.00298PC_Write_Retiring : 0.00231PC_Write_Retiring : 0.00171
BR_IMMED_Retiring : 0.00394BR_IMMED_Retiring : 0.00350BR_IMMED_Retiring : 0.00310BR_IMMED_Retiring : 0.00298BR_IMMED_Retiring : 0.00231BR_IMMED_Retiring : 0.00171
BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000
BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000
Metric_L1D_Miss_Ratio : 0.01625Metric_L1D_Miss_Ratio : 0.01791Metric_L1D_Miss_Ratio : 0.02479Metric_L1D_Miss_Ratio : 0.03246Metric_L1D_Miss_Ratio : 0.03458Metric_L1D_Miss_Ratio : 0.03515
Metric_L1D_RD_Miss_Ratio : 0.01692Metric_L1D_RD_Miss_Ratio : 0.01863Metric_L1D_RD_Miss_Ratio : 0.02567Metric_L1D_RD_Miss_Ratio : 0.03369Metric_L1D_RD_Miss_Ratio : 0.03581Metric_L1D_RD_Miss_Ratio : 0.03639
Metric_L1D_WR_Miss_Ratio : 0.00264Metric_L1D_WR_Miss_Ratio : 0.00239Metric_L1D_WR_Miss_Ratio : 0.00307Metric_L1D_WR_Miss_Ratio : 0.00338Metric_L1D_WR_Miss_Ratio : 0.00379Metric_L1D_WR_Miss_Ratio : 0.00390
Metric_L2D_Miss_Ratio : 0.02740Metric_L2D_Miss_Ratio : 0.19737Metric_L2D_Miss_Ratio : 0.19336Metric_L2D_Miss_Ratio : 0.14853Metric_L2D_Miss_Ratio : 0.15673Metric_L2D_Miss_Ratio : 0.18801
Metric_L2D_RD_Miss_Ratio : 0.05446Metric_L2D_RD_Miss_Ratio : 0.39807Metric_L2D_RD_Miss_Ratio : 0.38924Metric_L2D_RD_Miss_Ratio : 0.29803Metric_L2D_RD_Miss_Ratio : 0.31396Metric_L2D_RD_Miss_Ratio : 0.37706
Metric_L2D_WR_Miss_Ratio : 0.00004Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000
Metric_L3D_Miss_Ratio : 0.00000Metric_L3D_Miss_Ratio : 0.00010Metric_L3D_Miss_Ratio : 0.00160Metric_L3D_Miss_Ratio : 0.02646Metric_L3D_Miss_Ratio : 0.18870Metric_L3D_Miss_Ratio : 0.23623
Metric_L3D_RD_Miss_Ratio : 0.00000Metric_L3D_RD_Miss_Ratio : 0.00020Metric_L3D_RD_Miss_Ratio : 0.00325Metric_L3D_RD_Miss_Ratio : 0.05356Metric_L3D_RD_Miss_Ratio : 0.38055Metric_L3D_RD_Miss_Ratio : 0.47494
Metric_BR_Mispred_Ratio : 0.01048Metric_BR_Mispred_Ratio : 0.00500Metric_BR_Mispred_Ratio : 0.00346Metric_BR_Mispred_Ratio : 0.00211Metric_BR_Mispred_Ratio : 0.00158Metric_BR_Mispred_Ratio : 0.00131
Metric_L1I_TLB_Miss_Ratio : 0.00001Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000
Metric_L1D_TLB_Miss_Ratio : 0.00087Metric_L1D_TLB_Miss_Ratio : 0.00432Metric_L1D_TLB_Miss_Ratio : 0.00584Metric_L1D_TLB_Miss_Ratio : 0.00984Metric_L1D_TLB_Miss_Ratio : 0.01323Metric_L1D_TLB_Miss_Ratio : 0.01621
Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00001Metric_L2_TLB_Miss_Ratio : 0.00005Metric_L2_TLB_Miss_Ratio : 0.00035Metric_L2_TLB_Miss_Ratio : 0.02917Metric_L2_TLB_Miss_Ratio : 0.04803
Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000
Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00039Metric_DTLB_Table_Walk_Ratio : 0.00078
Metric_Load_Port_Util : 0.17082Metric_Load_Port_Util : 0.16742Metric_Load_Port_Util : 0.15939Metric_Load_Port_Util : 0.15151Metric_Load_Port_Util : 0.12046Metric_Load_Port_Util : 0.09069
Metric_Store_Port_Util : 0.09640Metric_Store_Port_Util : 0.09578Metric_Store_Port_Util : 0.09422Metric_Store_Port_Util : 0.08822Metric_Store_Port_Util : 0.07090Metric_Store_Port_Util : 0.05370
Metric_Neon_Port_Util : 0.35740Metric_Neon_Port_Util : 0.34510Metric_Neon_Port_Util : 0.33232Metric_Neon_Port_Util : 0.31449Metric_Neon_Port_Util : 0.25020Metric_Neon_Port_Util : 0.18842
Metric_GFLOPs_Use : 5.73161Metric_GFLOPs_Use : 5.50208Metric_GFLOPs_Use : 5.24582Metric_GFLOPs_Use : 4.97877Metric_GFLOPs_Use : 3.95044Metric_GFLOPs_Use : 3.03964

Block_mperf

M=N=K=100M=N=K=200M=N=K=300M=N=K=500M=N=K=700M=N=K=900
Frontend_Bound : 0.00050Frontend_Bound : 0.00014Frontend_Bound : 0.00013Frontend_Bound : 0.00013Frontend_Bound : 0.00016Frontend_Bound : 0.00014
Fetch_Latency : 0.00050Fetch_Latency : 0.00014Fetch_Latency : 0.00013Fetch_Latency : 0.00013Fetch_Latency : 0.00016Fetch_Latency : 0.00014
ICache_Misses : 0.00028ICache_Misses : 0.00004ICache_Misses : 0.00003ICache_Misses : 0.00005ICache_Misses : 0.00004ICache_Misses : 0.00003
ITLB_Misses : 0.00001ITLB_Misses : 0.00000ITLB_Misses : 0.00000ITLB_Misses : 0.00004ITLB_Misses : 0.00002ITLB_Misses : 0.00001
Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000
Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000
Bad_Speculation : 0.48119Bad_Speculation : 0.46947Bad_Speculation : 0.46177Bad_Speculation : 0.42173Bad_Speculation : 0.39518Bad_Speculation : 0.37718
Branch_Mispredicts : 134.60001Branch_Mispredicts : 471.60001Branch_Mispredicts : 1535.69995Branch_Mispredicts : 7051.50000Branch_Mispredicts : 20853.69922Branch_Mispredicts : 46702.60156
Backend_Bound : 0.18770Backend_Bound : 0.20837Backend_Bound : 0.22868Backend_Bound : 0.28475Backend_Bound : 0.33877Backend_Bound : 0.36801
Memory_Bound : 0.05038Memory_Bound : 0.07006Memory_Bound : 0.09758Memory_Bound : 0.14764Memory_Bound : 0.23551Memory_Bound : 0.25875
Load_Bound : 0.04975Load_Bound : 0.06994Load_Bound : 0.09756Load_Bound : 0.14762Load_Bound : 0.23547Load_Bound : 0.25870
Load_DTLB : 0.00056Load_DTLB : 0.00291Load_DTLB : 0.00397Load_DTLB : 0.00647Load_DTLB : 0.01252Load_DTLB : 0.02023
Load_Cache : 0.04751Load_Cache : 0.06600Load_Cache : 0.08761Load_Cache : 0.13781Load_Cache : 0.21025Load_Cache : 0.23244
Store_Bound : 0.00063Store_Bound : 0.00012Store_Bound : 0.00002Store_Bound : 0.00002Store_Bound : 0.00004Store_Bound : 0.00005
Store_TLB : 0.00001Store_TLB : 0.00001Store_TLB : 0.00001Store_TLB : 0.00002Store_TLB : 0.00010Store_TLB : 0.00004
Store_Buffer : 0.00060Store_Buffer : 0.00011Store_Buffer : 0.00001Store_Buffer : 0.00001Store_Buffer : 0.00001Store_Buffer : 0.00001
Core_Bound : 0.13732Core_Bound : 0.13830Core_Bound : 0.13109Core_Bound : 0.13711Core_Bound : 0.10326Core_Bound : 0.10926
Interlock_Bound : 0.11610Interlock_Bound : 0.11333Interlock_Bound : 0.11263Interlock_Bound : 0.10552Interlock_Bound : 0.09648Interlock_Bound : 0.09286
Interlock_AGU : 0.00033Interlock_AGU : 0.00016Interlock_AGU : 0.00020Interlock_AGU : 0.00011Interlock_AGU : 0.00011Interlock_AGU : 0.00011
Interlock_FPU : 0.11562Interlock_FPU : 0.11310Interlock_FPU : 0.11235Interlock_FPU : 0.10536Interlock_FPU : 0.09633Interlock_FPU : 0.09271
Core_Bound_Others : 0.02122Core_Bound_Others : 0.02498Core_Bound_Others : 0.01846Core_Bound_Others : 0.03159Core_Bound_Others : 0.00678Core_Bound_Others : 0.01639
Retiring : 0.33061Retiring : 0.32202Retiring : 0.30943Retiring : 0.29339Retiring : 0.26590Retiring : 0.25467
LD_Retiring : 0.08509LD_Retiring : 0.08384LD_Retiring : 0.07989LD_Retiring : 0.07608LD_Retiring : 0.06889LD_Retiring : 0.06596
ST_Retiring : 0.04802ST_Retiring : 0.04796ST_Retiring : 0.04731ST_Retiring : 0.04436ST_Retiring : 0.04063ST_Retiring : 0.03914
DP_Retiring : 0.01579DP_Retiring : 0.01404DP_Retiring : 0.01267DP_Retiring : 0.01211DP_Retiring : 0.01071DP_Retiring : 0.01011
ASE_Retiring : 0.17804ASE_Retiring : 0.17281ASE_Retiring : 0.16650ASE_Retiring : 0.15789ASE_Retiring : 0.14306ASE_Retiring : 0.13700
VFP_Retiring : 0.17804VFP_Retiring : 0.17281VFP_Retiring : 0.16650VFP_Retiring : 0.15789VFP_Retiring : 0.14306VFP_Retiring : 0.13700
PC_Write_Retiring : 0.00393PC_Write_Retiring : 0.00350PC_Write_Retiring : 0.00315PC_Write_Retiring : 0.00302PC_Write_Retiring : 0.00266PC_Write_Retiring : 0.00251
BR_IMMED_Retiring : 0.00393BR_IMMED_Retiring : 0.00350BR_IMMED_Retiring : 0.00314BR_IMMED_Retiring : 0.00301BR_IMMED_Retiring : 0.00266BR_IMMED_Retiring : 0.00251
BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000
BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000
Metric_L1D_Miss_Ratio : 0.01534Metric_L1D_Miss_Ratio : 0.01732Metric_L1D_Miss_Ratio : 0.02081Metric_L1D_Miss_Ratio : 0.02163Metric_L1D_Miss_Ratio : 0.01878Metric_L1D_Miss_Ratio : 0.02113
Metric_L1D_RD_Miss_Ratio : 0.01645Metric_L1D_RD_Miss_Ratio : 0.01864Metric_L1D_RD_Miss_Ratio : 0.02260Metric_L1D_RD_Miss_Ratio : 0.02330Metric_L1D_RD_Miss_Ratio : 0.02030Metric_L1D_RD_Miss_Ratio : 0.02284
Metric_L1D_WR_Miss_Ratio : 0.00189Metric_L1D_WR_Miss_Ratio : 0.00186Metric_L1D_WR_Miss_Ratio : 0.00171Metric_L1D_WR_Miss_Ratio : 0.00194Metric_L1D_WR_Miss_Ratio : 0.00169Metric_L1D_WR_Miss_Ratio : 0.00189
Metric_L2D_Miss_Ratio : 0.03201Metric_L2D_Miss_Ratio : 0.19252Metric_L2D_Miss_Ratio : 0.21329Metric_L2D_Miss_Ratio : 0.23120Metric_L2D_Miss_Ratio : 0.26215Metric_L2D_Miss_Ratio : 0.23144
Metric_L2D_RD_Miss_Ratio : 0.06368Metric_L2D_RD_Miss_Ratio : 0.38713Metric_L2D_RD_Miss_Ratio : 0.42980Metric_L2D_RD_Miss_Ratio : 0.46448Metric_L2D_RD_Miss_Ratio : 0.52642Metric_L2D_RD_Miss_Ratio : 0.46396
Metric_L2D_WR_Miss_Ratio : 0.00006Metric_L2D_WR_Miss_Ratio : 0.00001Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000Metric_L2D_WR_Miss_Ratio : 0.00000
Metric_L3D_Miss_Ratio : 0.00041Metric_L3D_Miss_Ratio : 0.00010Metric_L3D_Miss_Ratio : 0.00089Metric_L3D_Miss_Ratio : 0.04055Metric_L3D_Miss_Ratio : 0.05405Metric_L3D_Miss_Ratio : 0.05183
Metric_L3D_RD_Miss_Ratio : 0.00096Metric_L3D_RD_Miss_Ratio : 0.00021Metric_L3D_RD_Miss_Ratio : 0.00180Metric_L3D_RD_Miss_Ratio : 0.08196Metric_L3D_RD_Miss_Ratio : 0.10890Metric_L3D_RD_Miss_Ratio : 0.10425
Metric_BR_Mispred_Ratio : 0.01047Metric_BR_Mispred_Ratio : 0.00499Metric_BR_Mispred_Ratio : 0.00515Metric_BR_Mispred_Ratio : 0.00506Metric_BR_Mispred_Ratio : 0.00559Metric_BR_Mispred_Ratio : 0.00598
Metric_L1I_TLB_Miss_Ratio : 0.00001Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000
Metric_L1D_TLB_Miss_Ratio : 0.00084Metric_L1D_TLB_Miss_Ratio : 0.00414Metric_L1D_TLB_Miss_Ratio : 0.00577Metric_L1D_TLB_Miss_Ratio : 0.00980Metric_L1D_TLB_Miss_Ratio : 0.01345Metric_L1D_TLB_Miss_Ratio : 0.01641
Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00001Metric_L2_TLB_Miss_Ratio : 0.00002Metric_L2_TLB_Miss_Ratio : 0.00049Metric_L2_TLB_Miss_Ratio : 0.02613Metric_L2_TLB_Miss_Ratio : 0.06261
Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000
Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00035Metric_DTLB_Table_Walk_Ratio : 0.00103
Metric_Load_Port_Util : 0.17019Metric_Load_Port_Util : 0.16767Metric_Load_Port_Util : 0.15977Metric_Load_Port_Util : 0.15216Metric_Load_Port_Util : 0.13779Metric_Load_Port_Util : 0.13191
Metric_Store_Port_Util : 0.09605Metric_Store_Port_Util : 0.09592Metric_Store_Port_Util : 0.09462Metric_Store_Port_Util : 0.08872Metric_Store_Port_Util : 0.08126Metric_Store_Port_Util : 0.07829
Metric_Neon_Port_Util : 0.35609Metric_Neon_Port_Util : 0.34562Metric_Neon_Port_Util : 0.33301Metric_Neon_Port_Util : 0.31577Metric_Neon_Port_Util : 0.28611Metric_Neon_Port_Util : 0.27400
Metric_GFLOPs_Use : 5.69725Metric_GFLOPs_Use : 5.51211Metric_GFLOPs_Use : 5.29374Metric_GFLOPs_Use : 4.99903Metric_GFLOPs_Use : 4.53463Metric_GFLOPs_Use : 4.37174

Pack_mperf

M=N=K=100M=N=K=200M=N=K=300M=N=K=500M=N=K=700M=N=K=900
Frontend_Bound : 0.00084Frontend_Bound : 0.00033Frontend_Bound : 0.00035Frontend_Bound : 0.00036Frontend_Bound : 0.00033Frontend_Bound : 0.00033
Fetch_Latency : 0.00084Fetch_Latency : 0.00033Fetch_Latency : 0.00035Fetch_Latency : 0.00036Fetch_Latency : 0.00033Fetch_Latency : 0.00033
ICache_Misses : 0.00009ICache_Misses : 0.00006ICache_Misses : 0.00012ICache_Misses : 0.00010ICache_Misses : 0.00008ICache_Misses : 0.00008
ITLB_Misses : 0.00001ITLB_Misses : 0.00000ITLB_Misses : 0.00013ITLB_Misses : 0.00003ITLB_Misses : 0.00002ITLB_Misses : 0.00002
Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000
Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000
Bad_Speculation : 0.29067Bad_Speculation : 0.29156Bad_Speculation : 0.27964Bad_Speculation : 0.26751Bad_Speculation : 0.24406Bad_Speculation : 0.22907
Branch_Mispredicts : 166.50000Branch_Mispredicts : 530.09998Branch_Mispredicts : 1718.09998Branch_Mispredicts : 7551.70020Branch_Mispredicts : 22910.50000Branch_Mispredicts : 50927.00000
Backend_Bound : 0.39938Backend_Bound : 0.40494Backend_Bound : 0.43232Backend_Bound : 0.46649Backend_Bound : 0.51691Backend_Bound : 0.53782
Memory_Bound : 0.03465Memory_Bound : 0.02105Memory_Bound : 0.05301Memory_Bound : 0.12115Memory_Bound : 0.20594Memory_Bound : 0.22456
Load_Bound : 0.03365Load_Bound : 0.02057Load_Bound : 0.05282Load_Bound : 0.12086Load_Bound : 0.20543Load_Bound : 0.22408
Load_DTLB : 0.00052Load_DTLB : 0.00052Load_DTLB : 0.00066Load_DTLB : 0.00105Load_DTLB : 0.00245Load_DTLB : 0.00548
Load_Cache : 0.02941Load_Cache : 0.01824Load_Cache : 0.05483Load_Cache : 0.10329Load_Cache : 0.20224Load_Cache : 0.21719
Store_Bound : 0.00100Store_Bound : 0.00048Store_Bound : 0.00020Store_Bound : 0.00029Store_Bound : 0.00051Store_Bound : 0.00048
Store_TLB : 0.00004Store_TLB : 0.00003Store_TLB : 0.00003Store_TLB : 0.00007Store_TLB : 0.00010Store_TLB : 0.00016
Store_Buffer : 0.00017Store_Buffer : 0.00006Store_Buffer : 0.00001Store_Buffer : 0.00001Store_Buffer : 0.00000Store_Buffer : 0.00001
Core_Bound : 0.36474Core_Bound : 0.38389Core_Bound : 0.37930Core_Bound : 0.34534Core_Bound : 0.31097Core_Bound : 0.31327
Interlock_Bound : 0.35229Interlock_Bound : 0.37519Interlock_Bound : 0.36953Interlock_Bound : 0.34252Interlock_Bound : 0.31283Interlock_Bound : 0.30781
Interlock_AGU : 0.00153Interlock_AGU : 0.00081Interlock_AGU : 0.00102Interlock_AGU : 0.00058Interlock_AGU : 0.00056Interlock_AGU : 0.00057
Interlock_FPU : 0.35022Interlock_FPU : 0.37414Interlock_FPU : 0.36819Interlock_FPU : 0.34176Interlock_FPU : 0.31210Interlock_FPU : 0.30707
Core_Bound_Others : 0.01244Core_Bound_Others : 0.00869Core_Bound_Others : 0.00978Core_Bound_Others : 0.00282Core_Bound_Others : -0.00185Core_Bound_Others : 0.00546
Retiring : 0.30911Retiring : 0.30317Retiring : 0.28769Retiring : 0.26564Retiring : 0.23871Retiring : 0.23278
LD_Retiring : 0.04459LD_Retiring : 0.04036LD_Retiring : 0.03691LD_Retiring : 0.03349LD_Retiring : 0.02966LD_Retiring : 0.02869
ST_Retiring : 0.00984ST_Retiring : 0.00510ST_Retiring : 0.00493ST_Retiring : 0.00279ST_Retiring : 0.00241ST_Retiring : 0.00230
DP_Retiring : 0.02618DP_Retiring : 0.02283DP_Retiring : 0.02146DP_Retiring : 0.01926DP_Retiring : 0.01710DP_Retiring : 0.01657
ASE_Retiring : 0.22220ASE_Retiring : 0.22917ASE_Retiring : 0.21917ASE_Retiring : 0.20533ASE_Retiring : 0.18532ASE_Retiring : 0.18116
VFP_Retiring : 0.22220VFP_Retiring : 0.22917VFP_Retiring : 0.21917VFP_Retiring : 0.20533VFP_Retiring : 0.18532VFP_Retiring : 0.18116
PC_Write_Retiring : 0.00675PC_Write_Retiring : 0.00592PC_Write_Retiring : 0.00538PC_Write_Retiring : 0.00488PC_Write_Retiring : 0.00430PC_Write_Retiring : 0.00414
BR_IMMED_Retiring : 0.00674BR_IMMED_Retiring : 0.00592BR_IMMED_Retiring : 0.00537BR_IMMED_Retiring : 0.00487BR_IMMED_Retiring : 0.00429BR_IMMED_Retiring : 0.00414
BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000
BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000
Metric_L1D_Miss_Ratio : 0.02724Metric_L1D_Miss_Ratio : 0.01994Metric_L1D_Miss_Ratio : 0.02942Metric_L1D_Miss_Ratio : 0.02552Metric_L1D_Miss_Ratio : 0.02491Metric_L1D_Miss_Ratio : 0.02444
Metric_L1D_RD_Miss_Ratio : 0.02309Metric_L1D_RD_Miss_Ratio : 0.01799Metric_L1D_RD_Miss_Ratio : 0.02617Metric_L1D_RD_Miss_Ratio : 0.02342Metric_L1D_RD_Miss_Ratio : 0.02275Metric_L1D_RD_Miss_Ratio : 0.02241
Metric_L1D_WR_Miss_Ratio : 0.27167Metric_L1D_WR_Miss_Ratio : 0.27029Metric_L1D_WR_Miss_Ratio : 0.28716Metric_L1D_WR_Miss_Ratio : 0.28674Metric_L1D_WR_Miss_Ratio : 0.29377Metric_L1D_WR_Miss_Ratio : 0.27893
Metric_L2D_Miss_Ratio : 0.10546Metric_L2D_Miss_Ratio : 0.28792Metric_L2D_Miss_Ratio : 0.31292Metric_L2D_Miss_Ratio : 0.34867Metric_L2D_Miss_Ratio : 0.35318Metric_L2D_Miss_Ratio : 0.34909
Metric_L2D_RD_Miss_Ratio : 0.22318Metric_L2D_RD_Miss_Ratio : 0.59666Metric_L2D_RD_Miss_Ratio : 0.63335Metric_L2D_RD_Miss_Ratio : 0.70160Metric_L2D_RD_Miss_Ratio : 0.70975Metric_L2D_RD_Miss_Ratio : 0.70086
Metric_L2D_WR_Miss_Ratio : 0.00763Metric_L2D_WR_Miss_Ratio : 0.00597Metric_L2D_WR_Miss_Ratio : 0.00049Metric_L2D_WR_Miss_Ratio : 0.00005Metric_L2D_WR_Miss_Ratio : 0.00006Metric_L2D_WR_Miss_Ratio : 0.00021
Metric_L3D_Miss_Ratio : 0.00000Metric_L3D_Miss_Ratio : 0.00004Metric_L3D_Miss_Ratio : 0.03019Metric_L3D_Miss_Ratio : 0.05627Metric_L3D_Miss_Ratio : 0.05840Metric_L3D_Miss_Ratio : 0.06148
Metric_L3D_RD_Miss_Ratio : 0.00000Metric_L3D_RD_Miss_Ratio : 0.00007Metric_L3D_RD_Miss_Ratio : 0.06132Metric_L3D_RD_Miss_Ratio : 0.11355Metric_L3D_RD_Miss_Ratio : 0.11756Metric_L3D_RD_Miss_Ratio : 0.12363
Metric_BR_Mispred_Ratio : 0.01086Metric_BR_Mispred_Ratio : 0.00510Metric_BR_Mispred_Ratio : 0.00516Metric_BR_Mispred_Ratio : 0.00507Metric_BR_Mispred_Ratio : 0.00574Metric_BR_Mispred_Ratio : 0.00609
Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000
Metric_L1D_TLB_Miss_Ratio : 0.00222Metric_L1D_TLB_Miss_Ratio : 0.00231Metric_L1D_TLB_Miss_Ratio : 0.00293Metric_L1D_TLB_Miss_Ratio : 0.00301Metric_L1D_TLB_Miss_Ratio : 0.00385Metric_L1D_TLB_Miss_Ratio : 0.00481
Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00049Metric_L2_TLB_Miss_Ratio : 0.00123Metric_L2_TLB_Miss_Ratio : 0.01338Metric_L2_TLB_Miss_Ratio : 0.07775Metric_L2_TLB_Miss_Ratio : 0.27862
Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000
Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00006Metric_DTLB_Table_Walk_Ratio : 0.00043Metric_DTLB_Table_Walk_Ratio : 0.00170
Metric_Load_Port_Util : 0.08919Metric_Load_Port_Util : 0.08072Metric_Load_Port_Util : 0.07381Metric_Load_Port_Util : 0.06698Metric_Load_Port_Util : 0.05932Metric_Load_Port_Util : 0.05737
Metric_Store_Port_Util : 0.01968Metric_Store_Port_Util : 0.01020Metric_Store_Port_Util : 0.00987Metric_Store_Port_Util : 0.00558Metric_Store_Port_Util : 0.00482Metric_Store_Port_Util : 0.00460
Metric_Neon_Port_Util : 0.44440Metric_Neon_Port_Util : 0.45834Metric_Neon_Port_Util : 0.43834Metric_Neon_Port_Util : 0.41067Metric_Neon_Port_Util : 0.37064Metric_Neon_Port_Util : 0.36232
Metric_GFLOPs_Use : 6.73893Metric_GFLOPs_Use : 7.27027Metric_GFLOPs_Use : 6.96883Metric_GFLOPs_Use : 6.63430Metric_GFLOPs_Use : 5.88770Metric_GFLOPs_Use : 5.75827

ASM_mperf

M=N=K=100M=N=K=200M=N=K=300M=N=K=500M=N=K=700M=N=K=900
max_err:0.000000max_err:0.000000max_err:0.000000max_err:0.000000max_err:0.000000max_err:0.000000
TAM STATIS RESULTS:TAM STATIS RESULTS:TAM STATIS RESULTS:TAM STATIS RESULTS:TAM STATIS RESULTS:TAM STATIS RESULTS:
Frontend_Bound : 0.00152Frontend_Bound : 0.00077Frontend_Bound : 0.00066Frontend_Bound : 0.00102Frontend_Bound : 0.00091Frontend_Bound : 0.00071
Fetch_Latency : 0.00152Fetch_Latency : 0.00077Fetch_Latency : 0.00066Fetch_Latency : 0.00102Fetch_Latency : 0.00091Fetch_Latency : 0.00071
ICache_Misses : 0.00044ICache_Misses : 0.00016ICache_Misses : 0.00027ICache_Misses : 0.00065ICache_Misses : 0.00055ICache_Misses : 0.00037
ITLB_Misses : 0.00001ITLB_Misses : 0.00001ITLB_Misses : 0.00000ITLB_Misses : 0.00009ITLB_Misses : 0.00003ITLB_Misses : 0.00004
Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000Predecode_Error : 0.00000
Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000Fetch_Bandwidth : 0.00000
Bad_Speculation : 0.25192Bad_Speculation : 0.13931Bad_Speculation : 0.10896Bad_Speculation : 0.02394Bad_Speculation : 0.07470Bad_Speculation : 0.06565
Branch_Mispredicts : 53.00000Branch_Mispredicts : 516.29999Branch_Mispredicts : 1237.50000Branch_Mispredicts : 6101.39990Branch_Mispredicts : 17442.59961Branch_Mispredicts : 37761.50000
Backend_Bound : 0.09611Backend_Bound : 0.06685Backend_Bound : 0.14100Backend_Bound : 0.32652Backend_Bound : 0.41993Backend_Bound : 0.45994
Memory_Bound : 0.06672Memory_Bound : 0.04390Memory_Bound : 0.12568Memory_Bound : 0.25850Memory_Bound : 0.40588Memory_Bound : 0.45154
Load_Bound : 0.05526Load_Bound : 0.03654Load_Bound : 0.12134Load_Bound : 0.25507Load_Bound : 0.40223Load_Bound : 0.44639
Load_DTLB : 0.00095Load_DTLB : 0.00132Load_DTLB : 0.00173Load_DTLB : 0.00268Load_DTLB : 0.00493Load_DTLB : 0.01282
Load_Cache : 0.04603Load_Cache : 0.02975Load_Cache : 0.10898Load_Cache : 0.25344Load_Cache : 0.38846Load_Cache : 0.42574
Store_Bound : 0.01146Store_Bound : 0.00736Store_Bound : 0.00434Store_Bound : 0.00343Store_Bound : 0.00365Store_Bound : 0.00515
Store_TLB : 0.00053Store_TLB : 0.00058Store_TLB : 0.00053Store_TLB : 0.00086Store_TLB : 0.00143Store_TLB : 0.00289
Store_Buffer : 0.00811Store_Buffer : 0.00488Store_Buffer : 0.00318Store_Buffer : 0.00185Store_Buffer : 0.00106Store_Buffer : 0.00071
Core_Bound : 0.02938Core_Bound : 0.02295Core_Bound : 0.01532Core_Bound : 0.06802Core_Bound : 0.01405Core_Bound : 0.00839
Interlock_Bound : 0.00353Interlock_Bound : 0.00220Interlock_Bound : 0.00274Interlock_Bound : 0.00144Interlock_Bound : 0.00120Interlock_Bound : 0.00117
Interlock_AGU : 0.00326Interlock_AGU : 0.00213Interlock_AGU : 0.00264Interlock_AGU : 0.00141Interlock_AGU : 0.00118Interlock_AGU : 0.00115
Interlock_FPU : 0.00000Interlock_FPU : 0.00000Interlock_FPU : 0.00000Interlock_FPU : 0.00000Interlock_FPU : 0.00000Interlock_FPU : 0.00000
Core_Bound_Others : 0.02585Core_Bound_Others : 0.02075Core_Bound_Others : 0.01258Core_Bound_Others : 0.06657Core_Bound_Others : 0.01285Core_Bound_Others : 0.00722
Retiring : 0.65045Retiring : 0.79307Retiring : 0.74938Retiring : 0.64852Retiring : 0.50446Retiring : 0.47370
LD_Retiring : 0.18266LD_Retiring : 0.21852LD_Retiring : 0.20725LD_Retiring : 0.17772LD_Retiring : 0.13824LD_Retiring : 0.12980
ST_Retiring : 0.02936ST_Retiring : 0.01946ST_Retiring : 0.01859ST_Retiring : 0.00998ST_Retiring : 0.00750ST_Retiring : 0.00690
DP_Retiring : 0.03776DP_Retiring : 0.03734DP_Retiring : 0.03561DP_Retiring : 0.02792DP_Retiring : 0.02162DP_Retiring : 0.02026
ASE_Retiring : 0.32465ASE_Retiring : 0.42233ASE_Retiring : 0.39544ASE_Retiring : 0.35224ASE_Retiring : 0.27398ASE_Retiring : 0.25727
VFP_Retiring : 0.32465VFP_Retiring : 0.42233VFP_Retiring : 0.39544VFP_Retiring : 0.35224VFP_Retiring : 0.27398VFP_Retiring : 0.25727
PC_Write_Retiring : 0.01224PC_Write_Retiring : 0.01246PC_Write_Retiring : 0.01099PC_Write_Retiring : 0.00911PC_Write_Retiring : 0.00689PC_Write_Retiring : 0.00636
BR_IMMED_Retiring : 0.01234BR_IMMED_Retiring : 0.01254BR_IMMED_Retiring : 0.01115BR_IMMED_Retiring : 0.00920BR_IMMED_Retiring : 0.00697BR_IMMED_Retiring : 0.00644
BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000BR_RETURN_Retiring : 0.00000
BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000BR_INDIRECT_Retiring : 0.00000
Metric_L1D_Miss_Ratio : 0.01772Metric_L1D_Miss_Ratio : 0.00919Metric_L1D_Miss_Ratio : 0.01592Metric_L1D_Miss_Ratio : 0.01209Metric_L1D_Miss_Ratio : 0.01184Metric_L1D_Miss_Ratio : 0.01207
Metric_L1D_RD_Miss_Ratio : 0.00917Metric_L1D_RD_Miss_Ratio : 0.00428Metric_L1D_RD_Miss_Ratio : 0.01234Metric_L1D_RD_Miss_Ratio : 0.00928Metric_L1D_RD_Miss_Ratio : 0.00943Metric_L1D_RD_Miss_Ratio : 0.00977
Metric_L1D_WR_Miss_Ratio : 0.47821Metric_L1D_WR_Miss_Ratio : 0.53998Metric_L1D_WR_Miss_Ratio : 0.27725Metric_L1D_WR_Miss_Ratio : 0.33759Metric_L1D_WR_Miss_Ratio : 0.28778Metric_L1D_WR_Miss_Ratio : 0.27197
Metric_L2D_Miss_Ratio : 0.10307Metric_L2D_Miss_Ratio : 0.26791Metric_L2D_Miss_Ratio : 0.30925Metric_L2D_Miss_Ratio : 0.33934Metric_L2D_Miss_Ratio : 0.34121Metric_L2D_Miss_Ratio : 0.33642
Metric_L2D_RD_Miss_Ratio : 0.21359Metric_L2D_RD_Miss_Ratio : 0.55121Metric_L2D_RD_Miss_Ratio : 0.62478Metric_L2D_RD_Miss_Ratio : 0.68300Metric_L2D_RD_Miss_Ratio : 0.68550Metric_L2D_RD_Miss_Ratio : 0.67536
Metric_L2D_WR_Miss_Ratio : 0.00678Metric_L2D_WR_Miss_Ratio : 0.00421Metric_L2D_WR_Miss_Ratio : 0.00030Metric_L2D_WR_Miss_Ratio : 0.00004Metric_L2D_WR_Miss_Ratio : 0.00003Metric_L2D_WR_Miss_Ratio : 0.00006
Metric_L3D_Miss_Ratio : 0.00015Metric_L3D_Miss_Ratio : 0.00014Metric_L3D_Miss_Ratio : 0.01822Metric_L3D_Miss_Ratio : 0.05453Metric_L3D_Miss_Ratio : 0.05917Metric_L3D_Miss_Ratio : 0.06384
Metric_L3D_RD_Miss_Ratio : 0.00034Metric_L3D_RD_Miss_Ratio : 0.00030Metric_L3D_RD_Miss_Ratio : 0.03700Metric_L3D_RD_Miss_Ratio : 0.11009Metric_L3D_RD_Miss_Ratio : 0.11916Metric_L3D_RD_Miss_Ratio : 0.12840
Metric_BR_Mispred_Ratio : 0.00552Metric_BR_Mispred_Ratio : 0.00864Metric_BR_Mispred_Ratio : 0.00648Metric_BR_Mispred_Ratio : 0.00745Metric_BR_Mispred_Ratio : 0.00798Metric_BR_Mispred_Ratio : 0.00826
Metric_L1I_TLB_Miss_Ratio : 0.00001Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000Metric_L1I_TLB_Miss_Ratio : 0.00000
Metric_L1D_TLB_Miss_Ratio : 0.00243Metric_L1D_TLB_Miss_Ratio : 0.00254Metric_L1D_TLB_Miss_Ratio : 0.00320Metric_L1D_TLB_Miss_Ratio : 0.00368Metric_L1D_TLB_Miss_Ratio : 0.00490Metric_L1D_TLB_Miss_Ratio : 0.00570
Metric_L2_TLB_Miss_Ratio : 0.00000Metric_L2_TLB_Miss_Ratio : 0.00002Metric_L2_TLB_Miss_Ratio : 0.00007Metric_L2_TLB_Miss_Ratio : 0.01111Metric_L2_TLB_Miss_Ratio : 0.04116Metric_L2_TLB_Miss_Ratio : 0.20023
Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000Metric_ITLB_Table_Walk_Ratio : 0.00000
Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00000Metric_DTLB_Table_Walk_Ratio : 0.00003Metric_DTLB_Table_Walk_Ratio : 0.00035Metric_DTLB_Table_Walk_Ratio : 0.00190
Metric_Load_Port_Util : 0.36531Metric_Load_Port_Util : 0.43704Metric_Load_Port_Util : 0.41450Metric_Load_Port_Util : 0.35545Metric_Load_Port_Util : 0.27647Metric_Load_Port_Util : 0.25961
Metric_Store_Port_Util : 0.05872Metric_Store_Port_Util : 0.03892Metric_Store_Port_Util : 0.03719Metric_Store_Port_Util : 0.01995Metric_Store_Port_Util : 0.01500Metric_Store_Port_Util : 0.01381
Metric_Neon_Port_Util : 0.64930Metric_Neon_Port_Util : 0.84466Metric_Neon_Port_Util : 0.79088Metric_Neon_Port_Util : 0.70447Metric_Neon_Port_Util : 0.54795Metric_Neon_Port_Util : 0.51453
Metric_GFLOPs_Use : 10.20137Metric_GFLOPs_Use : 13.45224Metric_GFLOPs_Use : 12.57732Metric_GFLOPs_Use : 10.50762Metric_GFLOPs_Use : 8.73145Metric_GFLOPs_Use : 8.13339

术语表

  1. TMA: 也即 Top-down Microarchitecture Analysis 的缩写。TMA 是 intel 工程师为分析 intel X86 cpu 微架构的性能瓶颈而总结的方法论,可参见 intel x86 TMA。一句话总结的话,TMA 就是一种在微架构层面自顶而下的瓶颈定位方法。mperf 在ARM cpu上实现了 TMA 的方法论,并进行了包括本文在内的实践验证。
  2. Core_Bound: This metric represents fraction of slots where Core non-memory issues were of a bottleneck. Shortage in hardware compute resources; or dependencies in software's instructions are both categorized under Core Bound. 表示 CPU 处理器后端非访存相关的 stall 引起的性能损失,通常包括 ALU 单元的资源不足,以及流水线上的指令依赖引起的 stall 等。
  3. Interlock_Bound: No operation issued due to the backend interlock. 表示 CPU 处理器后端因为发生了 pipeline interlock 而产生的 stall, pipeline interlock 就是 A 指令的执行依赖 B 指令某一个pipeline stage的结果,而 B 指令还没有执行到对应 stage,指令 A 就等 stall 等待依赖条件满足,比如 raw 依赖。考虑到本文中频繁出现关于处理器 pipeline 以及 pipeline interlock 相关的术语,如果读者对这部分概念比较模糊,推荐一个很好的教学文档 mips pipeline
  4. Interlock_FPU: No operation issued due to the backend, interlock, FPU. This event counts every cycle that issue is stalled and there is an interlock that is due to an FPU/NEON instruction. 这个指标是上面 Interlock_Bound 的子类别,表征由 FPU/NEON 指令的 pipeline interlock 而产生流水线停顿的比例,比如前文降低 Interlock_FPU 的试验中,如果循环体中只有一个 fmla v0.4s, v0.4s, v0.4s 指令,下一个循环 iter 的 fmla 指令需要读取 v0 的数值,这就依赖上一个 iter的fmla 指令更新完 v0,而fmla指令的latency是多个 cycle,也就造成了相邻 iter 见 fmla 指令的 interlock, 流水线中将产生大量 stall。
  5. Load_Cache: No operation issued due to the backend, load, Cache miss. 表征因为 Cache 读延迟导致的stall。
  6. Metric_Neon_Port_Util: 处理器后端 neon port 的利用率,计算公式是 ASE_SPEC/(CYCLES*NEON_PORTS),拿实际执行的 neon 指令数除以处理器运行的 cycle 和处理器后端支持 neon 操作的 port 端口数的乘积,ARM a55 的 NEON_PORTS 是 1,在这里用于表征处理器 neon 单元的利用率。
  7. Metric_L3D_RD_Miss_Ratio: L3 Cache 读的缺失率,计算公式是 L3D_CACHE_REFILL_RD/L3D_CACHE_RD。
  8. Metric_Load_Port_Util: 处理器后端 load port 的利用率,计算公式是 LD_SPEC/(CYCLES*LD_PORTS),拿实际执行的 load 指令数除以处理器运行的 cycle 数和处理器后端支持 load 操作的 port 端口数的乘积,ARM a55 的 LD_PORTS 是 1,在这里用于表征处理器 LD 单元的利用率。
  9. L1D_TLB_Miss_Ratio: 表征的是 L1D 的 TLB miss 的比例,L1D TLB miss 会触发 L2D TLB 的 read。
  10. L2D_TLB_REFILL: 表征的是 L2D 的 TLB miss 的数量,会触发昂贵的 page table walker。

更多 MegEngine 信息获取,您可以:查看文档GitHub 项目,欢迎参与 MegEngine 社区贡献,成为 Awesome MegEngineer,荣誉证书、定制礼品享不停。

编辑于 2023-05-16 10:23・IP 属地北京

文章被以下专栏收录