1

我在 C++ 项目中使用用 C 编写的高性能/并行图形库。它提供了一个结构stinger(图形数据结构)和类似的操作

int stinger_insert_edge_pair (struct stinger *G,
                          int64_t type, int64_t from, int64_t to,
                          double weight, int64_t timestamp) { .... }

然而,大多数时候,我不想指定时间戳、权重或类型。默认参数会很好。此外,类似 OOP 的界面会很好:G->insertEdge(u, v)而不是insert_edge_pair(G, u, v, ...).

所以我正在考虑创建一个看起来像的适配器

class Graph {

protected:

    stinger* stingerG;

public:

    /** default parameters ***/

    double defaultEdgeWeight = 1.0;


    /** methods **/

    Graph(stinger* stingerG);

     virtual void insertEdge(node u, node v, double weight=defaultEdgeWeight);

   };

该方法insertEdge(...)只需stinger_insert_edge_pair(this->stingerG, ...)使用适当的参数调用。

但是,性能是这里的一个关键方面。使用这样的适配器类有什么性能损失?与使用“裸”库相比,我是否应该期望性能下降?

4

3 回答 3

1

虚函数通常不能内联,因此函数调用会产生相同数量的开销(将参数推送到堆栈上,可能会中断管道和缓存等)。在实践中,例行函数调用非常快——大约为时钟周期。确定这是否合适的唯一方法是在您自己的应用程序上进行测试。

于 2012-11-28T12:17:02.973 回答
1

如果您使用琐碎inline的方法,编译器应在调用时内联它们,因此不会有任何性能损失。但是请注意,您不应该为此使用虚函数。

于 2012-11-28T12:19:08.367 回答
1

如果您的 insertEgde 只是转发对 stinger_insert_edge_pair 的调用,那么(很可能)在对 stinger_insert_edge_pair 的普通调用和 g->insertEdge 之间生成的代码没有区别(前提是您删除了虚拟说明符)。比较通过普通调用和适配器调用生成的汇编代码可以公平地了解适配器带来的开销。

insertEdge 必须是虚拟的吗?您是否打算拥有 Graph 的子类?但同样,与函数执行本身的实际成本相比,虚函数调用的成本几乎可以忽略不计。

于 2012-11-28T12:19:26.073 回答