1

Consider the following code to measure the time spent by a function:

// Preprocessor
#include <iostream>
#include <chrono>

// Benchmarking function
template <class Function, class... Args>
double benchmark(Function&& f, Args&&... args)
{
    using clock = std::chrono::high_resolution_clock;
    using duration = std::chrono::duration<double>;
    auto tbegin = clock::now();
    std::forward<Function>(f)(std::forward<Args>(args)...);
    auto tend = clock::now();
    return std::chrono::duration_cast<duration>(tend-tbegin).count();
}

// Some example
unsigned int f(unsigned int n)
{
    unsigned int r = 0;
    for (unsigned int i = 0; i < n; ++i)
        for (unsigned int j = 0; j < n; ++j)
            r += (i*n)%(j+i+1);
    return r;
}

// Main function
int main()
{
    std::cout<<f(8192)<<std::endl; // Takes time
    std::cout<<benchmark(f, 8192)<<std::endl; // Takes no time
    return 0;
}

A problem arises when the function f has no side effect: the compiler does not execute it. Is there a way to modify my benchmark function in a generic way in order to force the execution of f and prevent optimization.

Vincent
  • 57,703
  • 61
  • 205
  • 388
  • This is likely a compiler specific question. Inform which compilers you are targeting. – glampert Apr 22 '14 at 04:30
  • With gcc you can match and mix optimization levels on per-function basis: `unsigned int f(unsigned int n) __attribute__((optimize("-O0")));` – oakad Apr 22 '14 at 05:25
  • But really, you should consider using a more complicated measurement boilerplate, such as this one: https://github.com/boostorg/spirit/blob/master/optimization/measure.hpp. Check out the comments in there to see what sort of effort needs to be involved in preventing the compiler from "spoofing" the benchmark. – oakad Apr 22 '14 at 05:32
  • Sorry, I don't think this question has already an answer, nor that it's a duplicate. Putting `asm("");` somewhere inside `f` isn't a good solution for this problem: the `benchmark` function should take care of preventing compiler optimization and the user shouldn't modify the function to be measured. A possible solution is in the comment of oakad (but it's GCC specific). Another idea could be to read the result of `f` call into a `volatile` external variable (or, for void function, try with something like http://stackoverflow.com/q/17748059/3235496). – manlio Apr 23 '14 at 07:52

0 Answers0