为可选的评测代码执行进行高效设计

Efficient design for optional profiling code execution

本文关键字:高效 执行 代码 评测      更新时间:2023-10-16

一些上下文:

我有一个C++方法,它执行一些密集的计算(车辆路线问题变体的一些分支定界算法)。因此,在本准则中,效率至关重要。当我测试不同的技巧来实现最佳速度时,我最终实现了一个类StatGatherer,它在给定的算法运行过程中收集信息(即:找到了多少条可行的路径,有多少条有界,有多少个不可行…)

void doStuff(const shared_ptr<StatGatherer>& statGatherer = NULL)
{
//do some stuff
...
if (statGatherer != NULL && some unfeasibility condition)
statGatherer->countOneFeasiblePath();
//do more stuff
...
if (statGatherer != NULL && some bounding criterium on the current path)
statGatherer->countOneBoundedPath();
//do more stuff
...       
if (statGatherer != NULL && a whole path has been found)
statGatherer->countOneBoundedPath();
...
//...more information gathering triggered by certain events
}

这很好,但具有讽刺意味的是,这种涉及statGatherer的"评测"代码的存在大大减慢了算法的速度,因为上面的伪代码被执行了数千万次。即使没有提供statGatherer并且默认为null,它仍然比根本没有这个代码慢很多。

因此,我的问题如下:有没有一种设计可以让我实现同样的行为,但与根本没有这个代码相比,当我不需要收集统计数据时,不会损失效率?

我能想到的每一个模板解决方案似乎仍然需要像上面这样的运行时检查,所以仍然更耗时。

非常感谢你的帮助!

附言:我是新来的,所以我欢迎有建设性的反馈,让我的问题更清楚。

使用inline无所事事的实现在StatGatherer或mock类型上对函数进行模板化(并通过引用传递)。编译器将使用mock完全删除实例化中的伪调用。

一种避免需要模拟方法但需要原始方法中的if(statGatherer && ...) statGatherer->...(...);的替代方法是模拟指针:使模板参数为StatGatherer*或伪指针类型:

template<class T>
struct dummy_ptr {
operator T*() const {return nullptr;}
T* operator->() const {return nullptr;}
};