在对C 二进制文件进行基准测试时出现异常

编程语言 2026-07-11

我在实验室实习,正在做微架构方面的基准测试。我使用 https://github.com/FoRTE-Research/UlSWaP-Bench/tree/master,并修改了mainmain.c。

该基准的目标是在5秒内测量一个程序的最大执行次数,即在5秒内对某个二进制进行尽可能多的执行,并重复30次。

我把所有数据保存到一些txt文件里,并用Python绘制指标图表,但这一部分并不重要。

我发现有时在运行程序时会出现异常现象。

我先跑了5 次热身,以避免冷缓存,然后再进行这30次正式运行。

我从图表上看到,平均执行次数的标准差似乎有些异常。

以下是我的指标:

这是热身运行

7786
7817
7818
7818
7817

这是针对lorawan_up程序的正式运行:

116
7810
7811
7810
7811
7810
7809
7810
7809
7810
7810
7810
7810
7809
7809
7810
7810
7809
7809
7810
7809
7808
7810
7810
7811
7810
7809
7808
7809
7809

我不知道为什么会得到这么低的值,一些程序没有这个问题,有些基准测试根本不会发生,可能是Linux的问题吗?不过我并不这么认为,也可能是我的C 代码有问题,下面是已修改的mainmain.c:

#include "common.h"
#include "misc.h"
#include "warmup.h"
#include <asm-generic/errno-base.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>

int benchmark_main(void);
extern void hexstring(uint32_t num);

int main(int argc, char *argv[]) {
  char *profile = argv[1];
  char *bin = argv[2];
  char *machine = argv[3];

  printf("Running bench for machine: %s, using profile: %s\n", machine,
         profile);
  printf("Running %d warmup benchmarks.\n", WARMUP_RUN);
  printf("Running maximum benchmarks in %fs.\n", SECONDS_TO_RUN);
  printf("Running %d time the maximum benchmarks.\n", RUNS);

#ifdef CUSTOM_ARCH_STARTUP
  run_arch_startup();
#endif // CUSTOM_ARCH_STARTUP
#ifdef WARMUP_RUN
  printf("Running warmup benchmarks...\n");
  warmup_run(machine, bin, profile);
  printf("Warmup benchmarks finished.\n");
#endif
  printf("Running benchmarks...\n");

  int result_arr[RUNS];

  for (int i = 0; i < RUNS; i++) {

    // Define start and end timer variable
    time_t start, end;
    // Define the number of run than the program has make in 10 seconds
    int nb_r = 0;
    // Number of seconds elapsed
    double elapsed;
    // Define if the program should terminate or not
    int terminate = 1;
    // Start timer
    start = time(NULL);
    while (terminate) {
      // Get the time and compare with start
      end = time(NULL);
      elapsed = difftime(end, start);
      // End the program if the program run for more or equal to 10 seconds
      if (elapsed >= SECONDS_TO_RUN /* seconds */) {
        terminate = 0;
      } else {
        // Run the given benchmark
        benchmark_main();
        // Increment the number of benchmark run
        nb_r++;
      }
    }

    // Store the number of benchmark run in result_arr
    result_arr[i] = nb_r;
  }

  char result_file[60];
  // Don't handle result for now
  snprintf(result_file, "../logs/%s/%s/%s.txt", machine, profile, bin);
  // Open file, create if doesn't exist
  FILE *fp = fopen(result_file, "w");
  if (fp == NULL) {
    printf("Error opening profile result file. File coulnd't be opened.\n");
    exit(1);
  }
  for (int i = 0; i < RUNS; i++) {
    int nb = result_arr[i];
    fprintf(fp, "%d\n", nb);
  }
  fclose(fp);

#if CHECKSUM_TEST
  uint32_t checksum = get_benchmark_checksum();
  hexstring(checksum);
#endif // CHECKSUM_TEST

#ifdef CUSTOM_ARCH_FINISH
  run_arch_finish();
#endif // CUSTOM_ARCH_FINISH

  return 0;
}
// Number of time we run the `SECONDS_TO_RUN`
#define RUNS 30
// Number of seconds we run benchmarks until exit
#define SECONDS_TO_RUN 5.0
// Warm up run
#ifndef WARMUP_RUN
#define WARMUP_RUN 5
#endif // WARMUP_RUN

异常总是在实际运行的第一行发生。有时也会出现在第一、第二行。

解决方案

把测试改成从整秒的起点开始计时:

// Wait for beginning of second
start = time(NULL);
while ( start == time(NULL) )
    ;
// Start timer
start = time(NULL);

在Linux上,你也可以使用 clock_gettime()gettimeofday() 这样的函数来获得更高精度的时间。

无论如何,首次启动一个程序时可能会更慢,因为需要把它载入到缓存或缓冲区中。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章