2017-10-11 135 views
0

一些上下文:高效设计用于可选的分析执行代码

我具有执行一些计算集约(在车辆路径问题变异一些分支定界算法)一个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,它仍然比没有这个代码慢很多。

因此,我的问题是:是否有一种设计可以实现相同的行为,但在不需要收集统计信息的情况下,效率并没有下降,相比之下根本没有此代码?

我能想到的每个模板解决方案似乎仍然涉及到像上面那样的某种运行时检查,因此更耗时。

非常感谢您的帮助! PS:我在这里是新来的,所以我欢迎建设性的反馈意见,让我的问题更清晰。

+0

使用代码插对剖析。 – user0042

回答

1

StatGatherer内嵌不做任何实现(并通过引用传递)类型的函数进行模板化。编译器将用模拟完全删除实例化中的虚假调用。

这避免了模拟方法的需求,但需要从原始的if(statGatherer && ...) statGatherer->...(...);是嘲笑指针的替代:具有模板参数是任一StatGatherer*或虚设指针类型:

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

是的 - 编译时做出决定听起来像是个好主意。我想我不应该鼓励它,但#ifdef和#define也允许你在编译时作出决定。 – mcdowella

+0

感谢vm大卫,这似乎是个伎俩。与你所描述的只有不同之处在于,我通过StatGatherer类创建了一个数据成员以避免传递它,因为它实际上是由我的主例程中的子例程调用的。当StatGatherer是虚拟类时,开销实际上已经消失。 我也很高兴听到一些不需要编写虚拟代码的解决方案,只是为了让编译器感到开心。 – GloomyJul