使用googlebenchmark对简单代码进行基准测试的问题

ele*_*ora 6 c++

我想对这个简单的C代码进行基准测试:

float f(float x[], float y[]) {
  float p = 0;
  for (int i = 0; i <64; i++)
    p += x[i] * y[i];
  return p;
}
Run Code Online (Sandbox Code Playgroud)

我的动机是尝试不同的编译器标志以及gcc和clang来看看它有什么不同.

我找到了这个测试框架,并一直试图让它工作.虽然我是C++的新手,但这是我的最大努力:

#include <benchmark.h>
#include <benchmark_api.h>

#include <cstdio>
#include <random>

std::random_device seed;
std::mt19937 gen(seed());

float f(float* x, float* y) {
  float p = 0;
  for (int i = 0; i <64; i++) {
    p += x[i] * y[i];
  }
  return p;
}

void f_benchmark(benchmark::State& state) {
  while (state.KeepRunning()) {
    benchmark::DoNotOptimize(f((float*) state.range(0), (float*) state.range(1)));
  }
}

void args(benchmark::internal::Benchmark* b) {
  std::uniform_real_distribution<float> rand(0, 100);

  for (int i = 0; i < 10; i++) {
    float* x = new float[64];
    float* y = new float[64];

    for (int i = 0; i < 64; i++) {
      x[i] = rand(gen);
      y[i] = rand(gen);

      printf("%f %f\n", x[i], y[i]);
    }

    b->Args({(int) x, (int) y});
  }
}

BENCHMARK(f_benchmark)->Apply(args);

BENCHMARK_MAIN();
Run Code Online (Sandbox Code Playgroud)

要编译它我做:

g ++ -Ofast -Wall -std = c ++ 11 test.cpp -Ibenchmark/include/benchmark /Lbenchmark/src/-o test -lbenchmark -lpthread

这给了我:

test.cpp: In function ‘void f_benchmark(benchmark::State&)’:
test.cpp:20:54: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
     benchmark::DoNotOptimize(f((float*) state.range(0), (float*) state.range(1)));
[...]                                                                            
test.cpp: In function ‘void args(benchmark::internal::Benchmark*)’:
test.cpp:38:20: error: cast from ‘float*’ to ‘int’ loses precision [-fpermissive]
     b->Args({(int) x, (int) y});
                    ^
[...]
Run Code Online (Sandbox Code Playgroud)

我怎样才能摆脱这些警告,一般来说,我这样做了吗?

Con*_*tin 4

您的代码将 a 转换float*inta 并返回 a float*- 这可能会导致问题,因为sizeof(int)sizeof(float*)不能保证相同(即在 x86-64 上int是 32 位,而float*在 64 位上!)。您遇到此问题的原因可能是因为Args()仅支持int参数(它们应该用作一系列基准的索引,而不是用作函数中的实际函数参数)。要使用不同类型的参数,您可以:

A.使用全局变量来存储预先计算的随机数组

#include <benchmark.h>
#include <benchmark_api.h>

#include <cstdio>
#include <random>

std::random_device seed;
std::mt19937 gen(seed());

float x[64*10], y[64*10];

float f(float* x, float* y) {
  float p = 0;
  for (int i = 0; i <64; i++) {
    p += x[i] * y[i];
  }
  return p;
}

void f_benchmark(benchmark::State& state) {
  while (state.KeepRunning()) {
    benchmark::DoNotOptimize(f(&x[state.range(0)*64], &y[state.range(0)*64]));
  }
}

void args(benchmark::internal::Benchmark* b) {
  std::uniform_real_distribution<float> rand(0, 100);
  for (int i = 0; i < 64*10; i++) {
    x[i] = rand(gen);
    y[i] = rand(gen);
  }
  for (int i = 0; i < 10; ++i)
    b->Arg({ i });
}
BENCHMARK(f_benchmark)->Apply(args);
BENCHMARK_MAIN();
Run Code Online (Sandbox Code Playgroud)

B. 计算随机数作为基准函数的一部分(如果每次迭代确实需要不同的随机值,请选择此方法 - 需要相应地暂停/恢复计时,以不包括随机生成/内存分配的时间基准)即

#include <benchmark.h>
#include <benchmark_api.h>
#include <cstdio>
#include <random>

std::random_device seed;
std::mt19937 gen(seed());

float f(float* x, float* y) {
  float p = 0;
  for (int i = 0; i <64; i++) {
    p += x[i] * y[i];
  }
  return p;
}

void f_benchmark(benchmark::State& state) {
  state.PauseTiming();
  std::uniform_real_distribution<float> rand(0, 100);
  float* x = new float[64];
  float* y = new float[64];
  while (state.KeepRunning()) {
    for (int i = 0; i < 64; i++) {
      x[i] = rand(gen);
      y[i] = rand(gen);
    }
    state.ResumeTiming();
    benchmark::DoNotOptimize(f(x, y));
    state.PauseTiming();
  }
  delete[] x;
  delete[] y;
}


BENCHMARK(f_benchmark)->Apply([](benchmark::internal::Benchmark* b){
  for (int i = 0; i < 10; ++i)
    b->Arg({ i });
});

BENCHMARK_MAIN();
Run Code Online (Sandbox Code Playgroud)

旁注:还要注意for循环中的内存泄漏 - 您应该delete[]为每个new[]运算符调用一次运算符。