Problems comparing simple code with googlebenchmark

I want to compare this simple C code:

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

My motivation is to try different compiler flags, as well as gcc and clang, to find out what the difference is.

I found this test structure and tried to make it work. Although I am completely new to C ++, here are my best efforts:

 #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(); 

To compile it, follow these steps:

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

This gives me:

 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}); ^ [...] 

How can I get rid of these warnings and in general, am I doing this right?

+6
source share
1 answer

Your code discards from float* to int and back to float* - this can cause problems because sizeof(int) and sizeof(float*) not guaranteed the same (i.e. on x86-64 int 32bit, and float* - 64 bit!). The reason you ran into this problem is probably because Args() only supports int arguments (they should be used as an index for the family of benchmarks, and not as actual function arguments in your function). To use another type of parameter, you can:

a. use global variables to store a pre-computed random array i.e.

 #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(); 

B. calculate random numbers as part of the reference function (choose this approach if you really need different random values ​​for each iteration - you need to pause / resume time so as not to include time for random generation / memory allocation in the control plan) i.e.

 #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(); 

Note. Also note the memory leak in the for loop - you must call the delete[] statement once for each new[] statement.

+3
source

Source: https://habr.com/ru/post/1014973/


All Articles