2014-10-01 1 views
1

Исходя из python Я пытаюсь найти способ вызвать несколько вызовов функций в коде C++. Пока я использую это.синхронизация множества вызовов функций

void my_func(/*some args*/) { 
    clock_t t_begin = std::clock(); 
    // code 
    clock_t t_end = std::clock(); 
    double elapsed_secs_U = double(t_end - t_begin)/CLOCKS_PER_SEC; 
} 

Но это очень повторяющееся явление. И я хотел бы иметь что-то вроде функции оболочки, так что я могу написать:

void timer(func, *args) { 
    clock_t t_begin = std::clock(); 
    func(*args) 
    clock_t t_end = std::clock(); 
    double elapsed_secs_U = double(t_end - t_begin)/CLOCKS_PER_SEC; 
} 

, которые могут быть использованы как:

timer(compute_a, a, b) 
timer(compute_b, b, c) 

Есть ли способ для достижения этой цели в C++?

PS: Мне нужны тайминги в продуктивных прогонах, таким образом, я не хочу, чтобы перекомпилировать код с профилирующими флагами и вставить его в Valgrind или любого другой инструмент

+0

Я думаю, вы могли бы сделать несколько [variadic template] (http://en.wikipedia.org/wiki/Variadic_template), делая это, используя [C++ 11] (Http://en.wikipedia.org/wiki/C++11). Или просто макрос [препроцессор] (http://en.wikipedia.org/wiki/C_preprocessor). –

ответ

4

Использование VARIADIC шаблона, вы можете сделать что-то вроде:

template <typename F, typename ... Ts> 
void timer(F f, Ts&&...args) { 
    clock_t t_begin = std::clock(); 
    f(std::forward<Ts>(args)...); 
    clock_t t_end = std::clock(); 
    double elapsed_secs_U = double(t_end - t_begin)/CLOCKS_PER_SEC; 
} 

Но просто

template <typename F> 
void timer(F f) { 
    clock_t t_begin = std::clock(); 
    f(); 
    clock_t t_end = std::clock(); 
    double elapsed_secs_U = double(t_end - t_begin)/CLOCKS_PER_SEC; 
} 

должен делать эту работу, и передать захватывая лямбда, когда вам нужно передать аргумент:

timer([&](){ compute_b(b, c);}); 
0

я использовал эту модель в прошлом. Это фиксирует общее время, проведенное в функции, на весь срок службы программы, а не на время, затраченное на один вызов.

struct FunctionTimer 
{ 
    FunctionTimer(std::string const& fname) : fname_(fname), totalTime_(0) {} 

    ~FunctionTimer() 
    { 
     std::cout << "Total time in " << fname_ << ": " << totalTime_ << std::endl; 
    } 

    std::string fname_; 
    double totalTime_; 
}; 

struct TimeAccumulator 
{ 
    TimeAccumulator(FunctionTimer& timer) : timer_(timer), begin_(std::clock()) {} 
    ~TimeAccumulator() 
    { 
     clock_t end = std::clock(); 
     double elapsed_secs = double(end - begin_)/CLOCKS_PER_SEC; 
     timer_.totalTime_ += elapsed_secs; 
    } 

    clock_t begin_; 
    FunctionTimer& timer_; 
}; 

void my_func(/*some args*/) 
{ 
    static FunctionTimer timer("my_func"); 
    TimeAccumulator acc(timer); 

    // code 
} 

Если вы хотели бы создать функцию-оболочку для целей синхронизации и оставить остальные функции нетронутым, некоторые шаблоны магией мощи сделать трюк. Мне нужно подумать о том, как такой шаблон функции может быть реализован.

+0

Но все-таки мне нужно было бы изменить все мои funcs вместо того, чтобы просто называть их через 'timer (my_func)'? – greole

+0

@greole, это метод, который я использовал в прошлом. Я завернул две строки кода в макрос, чтобы включить/отключить их во время компиляции на единицу компиляции. –