# CPU 性能测试

## 测试原理

`CoreMark` 是一个广泛用于评估嵌入式系统 CPU 性能的基准测试程序。其测试核心是通过模拟一些典型的嵌入式应用计算任务，来评估 CPU 在常见计算模式下的表现，测试的核心是基于以下几个要素：

- 算法选择： CoreMark 使用了以下几种基础的算法和操作：
  - 整数运算：包括加法、乘法、位操作等常见操作。
  - 数据结构：测试包含了链表、队列等数据结构的操作。
  - 控制结构：涉及循环、条件判断等基本的控制结构。
  - 矩阵乘法和基本计算任务：用来模拟常见的数值计算任务。
- 测试任务： CoreMark 测试的工作负载包括了下列几个方面：
  - 计算密集型操作：例如整数加法、乘法和位运算。
  - 内存操作：模拟典型的内存访问模式，包括链表和队列的操作。
  - 任务调度和控制：涉及复杂的控制流，例如条件判断和循环。
- 测试环境： CoreMark 的测试运行是在没有其他进程或线程干预的环境中执行的，这种方式确保了测试结果不受操作系统调度、资源管理等因素的影响，从而真实反映处理器的计算性能。
- 性能测量： CoreMark 的性能指标是 CoreMark 分数 (CoreMark score) ，这个分数反映了在测试期间执行的算法和任务的平均计算速度，分数越高，表示处理器的性能越好。

## 测试准备工作

**1.** 长时间高负载测试可能导致 CPU 温度升高，从而触发温控机制（如自动降频），影响测试结果。确保测试环境通风良好，散热正常。

**2.** 为避免其他进程干扰，建议关闭无关的后台程序，可以使用 `top` 命令查看并停止不必要的服务。

**3.** 在 app/platform_samples/chip_base_test/08_cpu_performance/coremark-main 路径下，已经提供了两个工具：`coremark_O3_multi` 和 `coremark_O3_single`，分别用于测试 O3 优化下的多核与单核性能。

如果已经烧录了 app.img ，可 `cd` 到如下路径查看 :

```shell
cd /app/platform_samples/chip_base_test/08_cpu_performance/coremark-main/

root@buildroot:/app/platform_samples/chip_base_test/08_cpu_performance/coremark-main# ls
LICENSE.md  README.md  barebones         core_main.c    core_state.c  coremark.h    coremark_O3_multi   cygwin  freebsd  macos  rtems
Makefile    aarch64    core_list_join.c  core_matrix.c  core_util.c   coremark.md5  coremark_O3_single  docs    linux    posix  simple
```

**检测 cpu 工作频率与温度：**
使用命令 hrut_somstatus 来查看 CPU、 GPU、 BPU 等模块的频率与温度信息：

```shell
hrut_somstatus
=====================1=====================
temperature-->
        DDR      : 54.1 (C)
        BPU      : 53.4 (C)
        CPU      : 53.5 (C)
cpu frequency-->
              min(M)    cur(M)  max(M)
        cpu0: 300       1500    1500
        cpu1: 300       1500    1500
        cpu2: 300       1500    1500
        cpu3: 300       1500    1500
        cpu4: 300       1500    1500
        cpu5: 300       1500    1500
        cpu6: 300       1500    1500
        cpu7: 300       1500    1500
bpu status information---->
              min(M)    cur(M)  max(M)  ratio
        bpu0: 500       1000    1000    0
ddr frequency information---->
              min(M)    cur(M)  max(M)
        ddr:  266       4266    4266
GPU gc8000 frequency information---->
              min(M)    cur(M)  max(M)
        gc8000:  200    1000    1000
```

**手动设置 cpu 频率：**
设置 CPU 运行在性能模式下，命令如下：

```shell
echo userspace >/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
echo 1500000 >/sys/devices/system/cpu/cpufreq/policy0/scaling_setspeed
```

## 测试方法

**1. 执行单核测试（coremark_O3_single**）

确保准备工作部分的一致性后，执行命令：

```shell
./coremark_O3_single
```

等待 10 秒后得到以下结果：

```yaml
2K performance run parameters for coremark.
CoreMark Size    : 666
Total ticks      : 16665
Total time (secs): 16.665000
Iterations/Sec   : 6600.660066
Iterations       : 110000
Compiler version : GCC11.3.1 20220712
Compiler flags   :  -O3 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55  -lrt
Memory location  : Please put data memory location here
                        (e.g. code in flash, data on heap etc)
seedcrc          : 0xe9f5
[0]crclist       : 0xe714
[0]crcmatrix     : 0x1fd7
[0]crcstate      : 0x8e3a
[0]crcfinal      : 0x33ff
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 6600.660066 / GCC11.3.1 20220712  -O3 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55  -lrt / Heap
```

**2. 执行多核测试（coremark_O3_multi**）

确保准备工作部分的一致性后，执行命令：

```shell
./coremark_O3_multi
```

```yaml
2K performance run parameters for coremark.
CoreMark Size    : 666
Total ticks      : 16620
Total time (secs): 16.620000
Iterations/Sec   : 52948.255114
Iterations       : 880000
Compiler version : GCC11.3.1 20220712
Compiler flags   :  -O3 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55 -DMULTITHREAD=8 -DUSE_PTHREAD -DVALIDATION_RUN=1  -lrt -pthread  -lrt
Parallel PThreads : 8
Memory location  : Please put data memory location here
                        (e.g. code in flash, data on heap etc)
seedcrc          : 0xe9f5
[0]crclist       : 0xe714
[1]crclist       : 0xe714
[2]crclist       : 0xe714
[3]crclist       : 0xe714
[4]crclist       : 0xe714
[5]crclist       : 0xe714
[6]crclist       : 0xe714
[7]crclist       : 0xe714
[0]crcmatrix     : 0x1fd7
[1]crcmatrix     : 0x1fd7
[2]crcmatrix     : 0x1fd7
[3]crcmatrix     : 0x1fd7
[4]crcmatrix     : 0x1fd7
[5]crcmatrix     : 0x1fd7
[6]crcmatrix     : 0x1fd7
[7]crcmatrix     : 0x1fd7
[0]crcstate      : 0x8e3a
[1]crcstate      : 0x8e3a
[2]crcstate      : 0x8e3a
[3]crcstate      : 0x8e3a
[4]crcstate      : 0x8e3a
[5]crcstate      : 0x8e3a
[6]crcstate      : 0x8e3a
[7]crcstate      : 0x8e3a
[0]crcfinal      : 0x33ff
[1]crcfinal      : 0x33ff
[2]crcfinal      : 0x33ff
[3]crcfinal      : 0x33ff
[4]crcfinal      : 0x33ff
[5]crcfinal      : 0x33ff
[6]crcfinal      : 0x33ff
[7]crcfinal      : 0x33ff
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 52948.255114 / GCC11.3.1 20220712  -O3 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55 -DMULTITHREAD=8 -DUSE_PTHREAD -DVALIDATION_RUN=1  -lrt -pthread  -lrt / Heap / 8:PThreads

```

**结果参数解析说明：**

- **`CoreMark Size`**：表示 CoreMark 基准测试的代码和数据大小，单位是字节。在这个例子中， CoreMark Size 为 666 字节，指的是整个 CoreMark 测试代码的大小。
- **`Total ticks`**：表示测试过程中 CPU 使用的总时钟周期数。比如： 16665 表示测试总共耗费了 16665 个时钟周期。
- **`Total time (secs)`**：表示测试所用的总时间，单位是秒。
- **`Iterations/Sec`**：每秒执行的迭代次数，即单位时间内程序运行的次数，这里是 6600 次 / 秒，即评分公式的 `coremark` 分数。
- **`Iterations`**：表示整个测试过程中执行的总迭代次数。 110000 表示 CoreMark 基准测试在 16.665 秒的时间里执行了 110000 次测试循环。
- **`seedcrc`**： CRC 校验：这些是 循环冗余校验（ CRC）值，用于验证测试的正确性。
- **`Compiler flags`**： 编译器标志，这里是 `-O3` 和 `-lrt`。
- **`CoreMark 1.0`**： 对关键信息的汇总 , 6600 是 CoreMark 性能得分，表示每秒迭代次数，这个值越高，表示处理器性能越强。

## 测试指标

以下标准需要在系统无工作任务时且多次取平均值测试得到， CoreMark 标准评分公式为 :

![coremark_formula](_static/_images/8-cpu_performance/coremark_formula.png)

- `CoreMark Iterations/Sec`：表示每秒执行的 CoreMark 基准测试迭代次数，通常反映处理器的性能。越高的迭代次数意味着更强的计算能力。
- `CPU Clock (MHz)`：处理器的时钟频率，单位是 MHz（兆赫兹）。它反映了处理器运行的速度，时钟频率越高，理论上处理器每秒可以执行的操作越多。
- `CPU Cores`：处理器的核心数， CoreMark 可以在单核或多核模式下进行测试。

### 分数标准

- `-O3` 编译优化的 CoreMark ：在 x5 平台上，单核分数应达到 X > 4.2 。
- `-O2` 编译优化的 CoreMark ：在 x5 平台上，单核分数应达到 X > 3.7 。

### 如何理解评分标准

这两个评分标准（-O3 和 -O2 ）实际上为不同优化级别下处理器的性能表现设定了最低要求。这个评分的意义在于：

- -O3 优化是 GCC 和其他编译器中的最高优化级别，通过激进的优化策略来提高执行速度。-O3 优化级别会开启很多性能优化特性，如循环展开、内联函数等，目标是获得更高的计算性能。
- -O2 优化 是相对较为保守的优化级别。相比于 -O3 ，-O2 优化不会启用一些可能导致代码大小增加的激进优化。因此，-O2 优化通常会得到更平衡的性能表现，并且能兼顾性能和可移植性。

根据 -O3 优化下单核测试的评分结果计算， CoreMark Iterations/Sec = 6600 次 / 秒， CPU Clock (MHz) = 1500 MHz， CPU Cores = 1 核（单核测试），根据公式计算 `CoreMark Score = 6600 /（ 1500 x 1 ） = 4.4`, 其结果大于 4.2 ，说明在单核处理器在这种优化级别下性能较好且符合测试要求。

根据 -O3 优化下多核测试的评分结果计算， CoreMark Iterations/Sec = 52948 次 / 秒， CPU Clock (MHz) = 1500 MHz， CPU Cores = 8 核（多核测试），根据公式计算 `CoreMark Score = 52948 /（ 1500 x 8 ） ≈ 4.41` , 其结果大于 4.2 ，说明多核处理器在这种优化级别下性能较好且符合测试要求。

## 常见问题

**1. 问**：需要测试多核怎样开启 `-O2` 和 `-O3` 编译优化情况下的 coremark 指标 ?

**1. 答**：测试多核以及开启 `-O2` 编译优化情况下的 coremark 指标，需要重新编译 coremark 源码，通过设置编译选项参数得到需要的 coremark 程序。在 `app/platform_samples/chip_base_test/08_cpu_performance/coremark-main` 路径下，可以按照以下命令进行重新编译。

编译单核开启 `-O2` 的 coremark 命令：

```shell
make PORT_DIR=aarch64 XCFLAGS="-O2 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55" REBUILD=1 run1.log

mv coremark.exe coremark_O2_single
```

编译 8 核开启 `-O2` 的 coremark 命令：

```shell
make PORT_DIR=aarch64 XCFLAGS="-O2 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55 -DMULTITHREAD=8 -DUSE_PTHREAD -DVALIDATION_RUN=1  -lrt -pthread" REBUILD=1 run2.log

mv coremark.exe coremark_O2_mutli
```

编译单核开启 `-O3` 的 coremark 命令：

```shell
make PORT_DIR=aarch64 XCFLAGS="-O3 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55" REBUILD=1 run1.log

mv coremark.exe coremark_O3_single
```

编译 8 核开启 `-O3` 的 coremark 命令：

```shell
make PORT_DIR=aarch64 XCFLAGS="-O3 -funroll-all-loops -static --param max-inline-insns-auto=550 -DPERFORMANCE_RUN=1 -mcpu=cortex-a55 -DMULTITHREAD=8 -DUSE_PTHREAD -DVALIDATION_RUN=1  -lrt -pthread" REBUILD=1 run2.log

mv coremark.exe coremark_O3_multi
```
