0

I am trying to generalize my benchmarking function, by having it receive the function to benchmark as the first parameter and the number of iterations as the second.

But since the function to benchmark needs to receive additional parameters, I thought I would fill in the parameters in the body of a lambda function and pass that to the benchmarking function. (I think that is called currying?)

Anyway I can not get it to compile:

 main.cpp:43:62: error: invalid initialization of non-const reference of type ‘std::function<double*()>&’ from an rvalue of type ‘main(int, char**)::<lambda()>’ bench::bench([=](){rng::gpu_r_exp((int) 10e6, lambda);}, 50); 

The function declaration looks like this:

void bench(std::function<double*()>& funct_to_bench, int repeats); 

and I use it like this:

bench::bench([=](){rng::gpu_r_exp((int) 10e6, lambda);}, 50); 

Since the compiler bickers about non-const again, I should maybe add, that gpu_r_exp utilizes a global variable which stores the rngState (it also did not like non-const parameters in gpu_r_exp).

I am really stuck. I just want to fill in the parameters and pass the pre-prepared function handle to the benchmarking function, so that it can wrap a timer with a progress bar around it.

EDIT: I should add that the parameter called lambda is a double, which is the parameter of the exponential distribution and has nothing to do with the lambda function.

15
  • A lambda is not a std::function. You need to pass a std::function to the function since it requires a non-const lvalue reference. Commented May 26, 2020 at 19:20
  • @NathanOliver stackoverflow.com/questions/6458612/… the accepted answer says that option 1 works, and that is pretty much what I used, right? Commented May 26, 2020 at 19:24
  • 2
    Your function is using a std::function &, that's not the same as a std::function. non-const lvalue references (which std::function & is) do not allow for conversions. You have to give it exactly what it is. Commented May 26, 2020 at 19:25
  • 1
    @FelixB. In void foo(int&), the int& is a non-const lvalue refernce. In void foo(const int &) the const int & is a const lvalue reference. In void foo(int&&) the int&& is a rvalue reference. In void foo(const int&&) the consat int&& is a const rvalue reference. Commented May 26, 2020 at 19:28
  • 1
    @FelixB. No. Like I said: non-const lvalue references do not allow for conversions. You have to give it exactly what it is. Since a lambda is not a std::function it wont work. A const-lvalue reference does allow for conversions and will let the code work. Commented May 26, 2020 at 19:34

1 Answer 1

1

Given that the benchmark wrapper is small, it doesn't make sense to worry about what's passed in, or whether it can be converted to std::function. Just take what comes and as long as it can be called, you're golden:

template <typename Fun> void benchmarkCallable(size_t iterations, Fun &&callable) { //... while (iterations--) callable(); //.. } 

If you worry that the //... sections are getting unwieldy, you can factor them out into a class:

class ScopedBenchmark { // start time, other state needed, etc. public: ScopedBenchmark() { /* capture initial state */ } ~ScopedBenchmark() { /* dump results etc */ } }; template <typename Fun> void benchmarkCallable(size_t iterations, Fun &&callable) { ScopedBenchmark benchmark; while (iterations--) callable(); } int main() { benchmarkCallable(1'000'000, []{ printf("foo!\n"); }); } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.