4.5.3. CPU-BPU-DDR 压力测试

4.5.3.1. 测试原理

CPU-BPU-DDR 压力测试的测试原理主要涉及对 CPU、 BPU 和 DDR 在高负荷条件下的性能和稳定性进行评估,以下是这些组件压力测试的一些基本原理:

1. CPU DDR 压力测试

  • 测试目标:使用 stressapptest 工具模拟高负载环境,进行大量计算、数据处理和内存操作,测试系统在多线程并发任务下的性能。

  • 测试目的:验证 CPU 在长时间高负载下的稳定性与性能,确保 CPU 和 DDR 能在高负荷运行时维持正常工作,避免崩溃、过热或性能下降等问题。

  • stressapptest CPU 压测原理: CPU 压测主要通过多线程并发执行一些计算密集型的任务来实现,这些任务包括:计算密集型任务、多线程并行执行等。

    • 线程创建: stressapptest 通过 pthread_create() 来创建多个线程,每个线程执行计算任务,线程的数量通常由用户通过 -C 参数指定。

    for (int i = 0; i < num_threads; i++) {
      pthread_create(&threads[i], NULL, cpu_stress_function, (void*)i);
    }
    
    • 计算密集型任务:每个线程会执行一些计算密集型的操作,例如浮点数计算、内存读写等,这会消耗 CPU 资源。

    void* cpu_stress_function(void* arg) {
      while (true) {
          // Perform some CPU-intensive calculations
          double a = 3.14159265358979;
          for (int i = 0; i < 1000000; i++) {
              a = a * a * 3.14159;  // Simulate a calculation
          }
      }
      return NULL;
    }
    
    • 线程同步和管理:通过 pthread_join() 等函数确保线程的正确执行和同步。

  • stressapptest DDR 压测原理: DDR 内存 的压力测试主涉及大量的内存分配、访问和数据交换,通过高内存使用、频繁的内存读写操作、以及内存带宽的消耗来进行。

    • 内存分配: 在内存压力测试中, stressapptest 会根据 -M 参数(例如 -M 8192 )来分配指定大小的内存。

    void* allocate_memory(size_t size) {
      void* ptr = malloc(size);  // 分配指定大小的内存
      if (ptr == NULL) {
          perror("Memory allocation failed");
          exit(1);
      }
      return ptr;
    }
    
    • 内存读写操作 : stressapptest 会在分配的内存区域中进行大量的读取和写入,以下是一个简单的内存读写操作的例子:

    void stress_memory(void* ptr, size_t size) {
      volatile char* data = (volatile char*)ptr;
          for (size_t i = 0; i < size; i++) {
                  data[i] = (char)(i % 256);  // 写入数据
                  char temp = data[i];  // 读取数据
          }
    }
    
    • 线程访问内存: stressapptest 使用多线程来增加内存压力。多个线程并发地对内存进行访问,模拟高负载下内存的使用情况。

  • 命令分析:运行压测脚本后,运行如下命令: stressapptest -s "$stime" -M "$memory_size" -f /tmp/sat.io1 -f /tmp/sat.io2 -i "$io_threads" -m 8 -C 2 -W

    • -s "$stime": 这个参数指定了 测试的持续时间。

    • -M "$memory_size”: 这个参数指定了内存使用量,在源码中,-M 参数用于控制内存的分配大小。

    • -f /tmp/sat.io1 -f /tmp/sat.io2: -f 参数用于指定文件用于 I/O 测试。

    • -i "$io_threads": 该参数指定了用于 I/O 操作的线程数。

    • -m 8: 这个参数控制 内存压力的强度。

    • -C 2: 这个参数指定了进行压力测试时使用的 CPU 核心数。

    • -W: 这个参数启用了 写操作,意味着不仅进行内存的读取,还会进行写入操作。

2. BPU 压力测试

  • 测试目标: 通过运行 run-portion.sh 脚本,并利用 tc_hbdk3 工具调整 -b ( BPU 核心 )和 -p( BPU 负载比例 )参数,模拟不同的 BPU 负载场景,确保 BPU 在高负载下依然能够稳定工作并达到预期性能。

  • 测试目的:确保 BPU 在执行计算任务时,能够输出与预期相符的正确结果,检查 BPU 长时间高负载运行下仍能稳定工作,不出现崩溃或错误。

  • tc_hbdk3 BPU 压测原理: 通过加载包含大量计算任务的模型,利用 BPU 进行加速计算,从而实现对 BPU 的压力测试。

  • 命令分析: 运行压测脚本后,运行如下命令:tc_hbdk3 -t $1 -b $2 -f $HBM_FILE -i $SRC_FILE -n $MODEL_NAME -o $OUTPUT_0_0,$OUTPUT_0_1,$OUTPUT_1_0,$OUTPUT_1_1 -g 0 -c 0

    • -t $1 : 传递 $portion 参数的值,可以灵活地控制压力测试的强度,并且可以根据不同的测试需求来选择合适的负载水平。

    • -b $2 : 选择使用的 BPU 核心数。

    • -f $HBM_FILE:-f 参数指定了 HBM 文件。

    • -i $SRC_FILE: 该文件包含模型推理或训练时使用的输入数据,程序会从中读取数据并传递给 BPU 进行计算。

    • -n $MODEL_NAME: -n 参数指定了要加载和运行的 模型名称

    • -o $OUTPUT_0_0 : 这些输出文件用于保存计算结果或日志数据。

4.5.3.2. 准备工作

1. 开始压力测试前,需要在芯片上添加散热片,否则芯片可能会进入过温保护影响测试结果。

2. 确认在 /app/platform_samples/chip_base_test/01_cpu_bpu_ddr 路径下存在的文件是否完整:

01_cpu_bpu_ddr/
├── models
│   └── HBDK3_MODEL_2K
│       ├── input_0_feature_1x1088x2048x3_ddr_native.bin
│       ├── run.sh
│       └── x5
│           └── gen_I2004_ForTest2k_1x1088x2048x3.hbm
├── scripts
│   ├── run-portion.sh
│   ├── stop_test.sh
│   ├── stress_test.sh
│   └── stressapptest
└── tc_hbdk3

4.5.3.3. 测试方法

压测脚本支持输入后缀 -h 查看命令参数的说明 :

./stress_test.sh -h

Usage: ./stress_test.sh [options]

Options:
  -t <time>        Set the test duration (e.g., 2h for hours, 30m for minutes; default: 48h).
  -m <size>        Set the memory size for stress test in MB (default: 100).
  -i <threads>     Set the I/O threads for stress test (default: 4).
  -b <bpu_core>    Specify the BPU core to use (default: 0).
  -p <portion>     Set the BPU portion value (default: 100).
  -o <directory>   Set the output directory for logs (default: ../../log).
  -h, --help       Show this help message and exit.

Example:
  ./stress_test.sh -t 24h -m 200 -i 8 -p 80

各参数解析如下:

  • t <time>: 用于设置压力测试的持续时间 , 时间格式可以是小时(如 2h)或分钟(如 30m),默认值为 48 小时。

  • m <size>: 用于设置压力测试中内存的大小(单位: MB),默认值为 100MB。

  • i <threads>: 用于设置 I/O 线程的数量,默认值为 4 。

  • b <bpu_core>: 用于指定 BPU(基于处理单元)核心的编号,默认值为 0 。

  • p <portion>: 用于设置 BPU 负载的比例,默认值为 100 (即满负载)。

  • o <directory>: 用于设置日志输出的目录,默认值为 ../../log。

  • h, --help: 显示帮助信息并退出脚本。

示例: 例如,使用命令 ./stress_test.sh -t 24h -m 200 -i 8 -p 80 来运行一个 24 小时的压力测试,使用 200MB 内存, 8 个 I/O 线程, 80% 的 BPU 负载。

确保已完成准备工作后,运行测试命令:

cd /app/platform_samples/chip_base_test/01_cpu_bpu_ddr/scripts

./stress_test.sh

压测脚本通过 hrut_somstatus 命令来监控 stressapptest 的运行情况,运行脚本启动时的日志如下:

Running stress test with the following configuration:
  Stress Time: 48h hours (2880 seconds)
  Memory Size: 100 MB
  I/O Threads: 4
  BPU Core: 0
  BPU Portion: 100%
  Output directory: /app/platform_samples/chip_base_test/log
Starting CPU stress test...
nohup: redirecting stderr to stdout
Starting BPU stress test...
=====================1=====================
temperature-->
        DDR      : 84.0 (C)
83087
        BPU      : 82.9 (C)
        CPU      : 83.7 (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    98
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

hrut_somstatus 命令结果解析如下:

  • temperature :代表当前 DDR、 BPU、 CPU 的温度。

  • cpu frequency :分别代表 CPU 0-7 的最小运行频率、当前运行频率和最大运行频率( MHZ)。

  • bpu status information :代表 BPU 的最小、当前和最大运行频率,其中 ratio 代表 BPU 当前占用率。

执行 top 命令查看 CPU 的占用率

image-20240313201614942

其中每一行显示了一个 CPU 核心的状态,格式为:

%CpuX  :  user/system  idle [ 进度条 ]
  • %CpuX:表示 CPU 核心编号,例如 %Cpu0 表示第 0 核心。

  • user:该核心的 CPU 时间中,有多少比例是用于执行用户空间的进程(如应用程序、进程等)。

  • system:该核心的 CPU 时间中,有多少比例是用于执行内核空间的进程(内核操作)。

  • idle:该核心有多少时间是空闲的, cpu0 当前空闲为 1 。

  • 进度条:显示该核心的负载情况。每个进度条的长度反映了 CPU 的负载强度。

例如第一个核心 %Cpu0 , 50.8% 的时间是在执行用户进程, 48.7% 的时间是在执行内核操作(系统进程),空闲时间为 0%,即该核心几乎没有空闲时间。

4.5.3.4. 测试指标

测试程序启动后,会在 /app/platform_samples/chip_base_test/log 目录下产生 bpu-stressX.logcpu-stressX.log 两份日志文件用来记录压测时的状态,确保能够在压测中保持如下内容:

  • 能稳定运行 48 小时,不出现重启或挂死的情况。

  • 使用以下命令检查日志文件中是否存在 failerrortimeout 等异常打印。

cd "/app/platform_samples/chip_base_test/log/" && grep -iE 'error|fail|timeout' bpu-stress*.log cpu-stress*.log
  • 执行 TOP 命令查看 CPU、 BPU 占比情况,正常状态应稳定保持在 98-100% 区间。

测试结果

输入命令:

cd "/app/platform_samples/chip_base_test/log/" && grep -iE 'error|fail|timeout' bpu-stress*.log cpu-stress*.log

显示如下:

cpu-stress1.log:1970/01/01-02:11:11(UTC) Stats: Completed: 80944.00M in 14.24s 5685.54MB/s, with 0 hardware incidents, 0 errors
cpu-stress1.log:1970/01/01-02:11:11(UTC) Status: PASS - please verify no corrected errors
cpu-stress2.log:1970/01/01-00:10:29(UTC) Stats: Completed: 3300956.00M in 589.29s 5601.62MB/s, with 0 hardware incidents, 0 errors
cpu-stress2.log:1970/01/01-00:10:29(UTC) Status: PASS - please verify no corrected errors
cpu-stress3.log:1970/01/01-00:34:09(UTC) Stats: Completed: 236090.00M in 44.79s 5270.69MB/s, with 0 hardware incidents, 0 errors
cpu-stress3.log:1970/01/01-00:34:09(UTC) Status: PASS - please verify no corrected errors

打印信息中并未出现其他异常信息,且 errors 数量为 0 ,代表压测结果正常。