假设我要测试以下几种算法。
void AlgoA(int x)
{
// critical operations go here
}
void AlgoB(int x, int y)
{
// critical operations go here
}
我定义了Timer
,它接受指向函数的无参数指针。
void Timer(void (*f)(), unsigned short N = 1)
{
vector<unsigned long long> results;
for (unsigned short i = 0; i < N; i++)
{
chrono::steady_clock::time_point begin = chrono::steady_clock::now();
f();
chrono::steady_clock::time_point end = chrono::steady_clock::now();
unsigned long long interval = chrono::duration_cast<chrono::microseconds>(end - begin).count();
results.push_back(interval);
cout << "Elapsed time: " << interval << std::endl;
}
unsigned long long sum = 0;
for (unsigned long long x : results)
sum += x;
cout << "Average: " << sum / results.size() << endl;
}
需要包装器来准备输入。
void DoA()
{
int x;
// preparing x goes here
AlgoA(x);
}
void DoB()
{
int x, y;
// preparing x and y goes here
AlgoB(x, y);
}
void main()
{
Timer(DoA);
Timer(DoB);
}
缺点:Timer
还计算准备输入所用的时间。
优点:许多算法测试的通用Timer
。
我必须编写2个计时器,每个计时器用于算法测试。
void TimerA(void (*f)(int), int x, unsigned short N = 1)
{
vector<unsigned long long> results;
for (unsigned short i = 0; i < N; i++)
{
chrono::steady_clock::time_point begin = chrono::steady_clock::now();
f(x);
chrono::steady_clock::time_point end = chrono::steady_clock::now();
unsigned long long interval = chrono::duration_cast<chrono::microseconds>(end - begin).count();
results.push_back(interval);
cout << "Elapsed time: " << interval << std::endl;
}
unsigned long long sum = 0;
for (unsigned long long x : results)
sum += x;
cout << "Average: " << sum / results.size() << endl;
}
void TimerB(void (*f)(int, int), int x, int y, unsigned short N = 1)
{
vector<unsigned long long> results;
for (unsigned short i = 0; i < N; i++)
{
chrono::steady_clock::time_point begin = chrono::steady_clock::now();
f(x, y);
chrono::steady_clock::time_point end = chrono::steady_clock::now();
unsigned long long interval = chrono::duration_cast<chrono::microseconds>(end - begin).count();
results.push_back(interval);
cout << "Elapsed time: " << interval << std::endl;
}
unsigned long long sum = 0;
for (unsigned long long x : results)
sum += x;
cout << "Average: " << sum / results.size() << endl;
}
void main()
{
int x;
// preparing x goes here.
TimerA(AlgoA, x);
int y;
// preparing y goes here.
TimerB(AlgoB, x, y);
}
优点:计时器仅计算关键操作。
缺点:多个计时器,每个计时器都供算法测试。
有什么方法可以只创建一个Timer
,但不能计算准备输入所需的时间?
实际上,输入不仅是int
,还可以是struct
等,可以从与时间有关的IO中检索到。
答案 0 :(得分:2)
我必须承认,我没有看到问题。也许问题是您过度指定了要执行的操作。如果您要将可调用对象传递给方法并对其进行调用,则应为:
template <typename F>
void call_it(F f) {
// start timer
f();
// stop timer
}
现在您可以将几乎所有内容传递给它,例如:
int x = some_expensive_precalculation();
call_it( [&]() { method_to_time(x); });
请注意,由于未直接调用该函数,您可能会遇到少量开销。但是,与任何值得衡量的东西相比,我希望这可以忽略不计,而且通过编译器优化,可能根本没有开销。
答案 1 :(得分:2)
如果您想始终在计时器之外准备输入,可以将std::function
与std::bind
一起使用
void timer(std::function<void()> algorithm, unsigned short N = 1) {
// your timer code here
}
void algoA(int x)
{
// critical operations go here
}
void algoB(int x, int y)
{
// critical operations go here
}
int main() {
int x, y; // prepare input
timer(std::bind(algoA, x));
timer(std::bind(algoB, x, y));
}
答案 2 :(得分:2)
您可以使用可变参数模板并将参数转发给测试对象。</ p>
#include <chrono>
#include <iostream>
#include<vector>
using namespace std;
template<typename ... Args>
void benchmark(void (*f)(Args...), unsigned short N, Args&&... args)
{
vector<unsigned long long> results;
for (unsigned short i = 0; i < N; i++)
{
chrono::steady_clock::time_point begin = chrono::steady_clock::now();
f(std::forward<Args>(args)...);
chrono::steady_clock::time_point end = chrono::steady_clock::now();
unsigned long long interval = chrono::duration_cast<chrono::microseconds>(end - begin).count();
results.push_back(interval);
cout << "Elapsed time: " << interval << std::endl;
}
unsigned long long sum = 0;
for (unsigned long long x : results)
sum += x;
cout << "Average: " << sum / results.size() << endl;
}
void fun(int a, float b, char c) {
}
int main() {
benchmark(fun, 500, 42, 3.1415f, 'A');
return 0;
}
我认为,这种方法无法为N
设置默认参数。但这也许对您而言并不重要。