在 C++ 中为 class 函数计时
Timing a class function in C++
之前的 post、 展示了一种使用包装函数进行分析的简洁方法。我正在尝试使用其中一个分析器来分析我的 class 函数。
#include <cmath>
#include <string>
#include <chrono>
#include <algorithm>
#include <iostream>
template<typename Duration = std::chrono::microseconds,
typename F,
typename ... Args>
typename Duration::rep profile(F&& fun, Args&&... args) {
const auto beg = std::chrono::high_resolution_clock::now();
std::forward<F>(fun)(std::forward<Args>(args)...);
const auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<Duration>(end - beg).count();
}
探查器适用于普通函数,但我正在努力将 class 函数传递给探查器。
#include "Profiler.h"
int main()
{
Config projConfig = Config(projConfigDir);
std::string imagePath = projConfig.GetTIFF();
ImageVector images_vec = Image::LoadImagesVec(imagePath);
Detector detector = Detector(&projConfig);
auto time = profile<std::chrono::seconds>(&Detector::DetectImages, detector, images_vec);
//detector.DetectImages(images_vec); // if ran without profiler
std::string _detectTime("DetectImages time elapsed: " + std::to_string(time));
Logger::Info(_detectTime.c_str());
}
我无法编译代码。我收到以下错误消息。
term does not evaluate to a function taking 2 arguments
因为我无法将指向有界函数的指针传递给探查器,所以我尝试传入函数、调用函数的对象实例和函数的参数(不确定这是否是正确的方法)。但我怀疑未实现探查器来处理 class 方法。如果是这样,我应该如何修改探查器以便它可以接受 class 函数?
您可以使用 std::bind
创建可调用对象以调用 class 对象上的 class 方法。
然后您可以像传递任何 function/lambda.
一样将此可调用对象传递给您的 profile
函数
请注意,使用 std::bind
还支持固定一个或多个方法参数。
使用 std::placeholders
(如下所示)允许仅在调用绑定的可调用对象时指定它们。
参见下面的示例:
#include <chrono>
#include <iostream>
#include <functional>
#include <thread>
#include <string>
template<typename Duration = std::chrono::microseconds,
typename F,
typename ... Args>
typename Duration::rep profile(F&& fun, Args&&... args)
{
const auto beg = std::chrono::high_resolution_clock::now();
std::forward<F>(fun)(std::forward<Args>(args)...);
const auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<Duration>(end - beg).count();
}
struct MyClass
{
void Run(std::string const & s, double d)
{
std::cout << "My id: " << id << ", MyClass::Run(" << s << ", " << d << ")" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int id{ 333 };
};
int main()
{
MyClass c;
// Run without profiling:
c.Run("without", 2.3);
// Run with profiling:
auto f = std::bind(&MyClass::Run, &c, std::placeholders::_1, std::placeholders::_2);
auto time = profile<std::chrono::milliseconds>(f, "with", 23);
std::cout << "time: " << time << std::endl;
return 0;
}
输出:
My id: 333, MyClass::Run(without, 2.3)
My id: 333, MyClass::Run(with, 23)
time: 109
之前的 post、
#include <cmath>
#include <string>
#include <chrono>
#include <algorithm>
#include <iostream>
template<typename Duration = std::chrono::microseconds,
typename F,
typename ... Args>
typename Duration::rep profile(F&& fun, Args&&... args) {
const auto beg = std::chrono::high_resolution_clock::now();
std::forward<F>(fun)(std::forward<Args>(args)...);
const auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<Duration>(end - beg).count();
}
探查器适用于普通函数,但我正在努力将 class 函数传递给探查器。
#include "Profiler.h"
int main()
{
Config projConfig = Config(projConfigDir);
std::string imagePath = projConfig.GetTIFF();
ImageVector images_vec = Image::LoadImagesVec(imagePath);
Detector detector = Detector(&projConfig);
auto time = profile<std::chrono::seconds>(&Detector::DetectImages, detector, images_vec);
//detector.DetectImages(images_vec); // if ran without profiler
std::string _detectTime("DetectImages time elapsed: " + std::to_string(time));
Logger::Info(_detectTime.c_str());
}
我无法编译代码。我收到以下错误消息。
term does not evaluate to a function taking 2 arguments
因为我无法将指向有界函数的指针传递给探查器,所以我尝试传入函数、调用函数的对象实例和函数的参数(不确定这是否是正确的方法)。但我怀疑未实现探查器来处理 class 方法。如果是这样,我应该如何修改探查器以便它可以接受 class 函数?
您可以使用 std::bind
创建可调用对象以调用 class 对象上的 class 方法。
然后您可以像传递任何 function/lambda.
一样将此可调用对象传递给您的 profile
函数
请注意,使用 std::bind
还支持固定一个或多个方法参数。
使用 std::placeholders
(如下所示)允许仅在调用绑定的可调用对象时指定它们。
参见下面的示例:
#include <chrono>
#include <iostream>
#include <functional>
#include <thread>
#include <string>
template<typename Duration = std::chrono::microseconds,
typename F,
typename ... Args>
typename Duration::rep profile(F&& fun, Args&&... args)
{
const auto beg = std::chrono::high_resolution_clock::now();
std::forward<F>(fun)(std::forward<Args>(args)...);
const auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<Duration>(end - beg).count();
}
struct MyClass
{
void Run(std::string const & s, double d)
{
std::cout << "My id: " << id << ", MyClass::Run(" << s << ", " << d << ")" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
int id{ 333 };
};
int main()
{
MyClass c;
// Run without profiling:
c.Run("without", 2.3);
// Run with profiling:
auto f = std::bind(&MyClass::Run, &c, std::placeholders::_1, std::placeholders::_2);
auto time = profile<std::chrono::milliseconds>(f, "with", 23);
std::cout << "time: " << time << std::endl;
return 0;
}
输出:
My id: 333, MyClass::Run(without, 2.3)
My id: 333, MyClass::Run(with, 23)
time: 109