【问题标题】:Lookup table to Function Pointer Array C++ performance函数指针数组 C++ 性能的查找表
【发布时间】:2016-08-21 20:22:10
【问题描述】:

我有以下代码可以在我的电脑 (x86) 上模拟基本系统:

typedef void (*op_fn) ();

void add()
{
   //add Opcode
   //fetch next opcode
   opcodes[opcode]();
}

void nop()
{
   //NOP opcode
   //fetch next opcode
   opcodes[opcode]();
}

const op_fn opcodes[256] =
{
    add,
    nop,
    etc...
};

我通过opcodes[opcode]()将此称为“表” 我正在努力提高我的口译员的表现。 内联每个函数怎么样,比如

inline void add()
inline void nop()

这样做有什么好处吗?

有没有办法让它跑得更快? 谢谢

【问题讨论】:

  • 关于工作代码的问题对于codereview.stackexchange.com可能更好
  • 你能创建一个与你的模式相匹配的实际工作代码的玩具示例吗?即使有 3 个操作码?正如所写,您的伪代码可以隐藏大的性能问题。此外,“让它变得更好”是一个糟糕的问题。你的代码失败的明确方式更好,或者为什么有些事情是意外的。
  • @tobi303 这是示例/伪代码,与代码审查无关,在该站点上,我们需要真实的工作代码。见A guide to Code Review for Stack Overflow users
  • 如果每个操作码函数调用下一个函数,您将(很可能)最终耗尽堆栈空间。将 fetch-and-dispatch 代码移出操作码实现。

标签: c++ virtual-machine emulation machine-language opcodes


【解决方案1】:

“内联”的意思是“不发出函数调用;而是在编译时替换函数体。”

通过函数指针调用的意思是“进行函数调用,其细节要到运行时才能知道。”

这两个特点是根本对立的。 (您可以期望的最好的结果是,足够先进的编译器可以在非常有限的情况下静态确定通过函数指针调用哪个函数,并将其内联。)

switch 块通常实现为跳转表,它的开销可能比函数调用少,因此用switch 块替换函数指针数组并使用内联可能会有所不同。

【讨论】:

    【解决方案2】:

    inline 只是给你的编译器的一个提示,它不保证会进行任何内联。您应该阅读内联(可能是at the ISO C++ FAQ),因为过多的内联实际上会使您的代码变慢(通过代码膨胀和相关的虚拟内存垃圾)。

    【讨论】:

      【解决方案3】:

      仅仅因为你将一个方法标记为inline,它并不要求编译器这样做——它更像是一个提示而不是一个命令。

      鉴于您将操作码处理程序存储在数组中,编译器需要将函数的地址放入数组中,因此无法内联。

      您的方法实际上没有任何问题。如果您真的认为自己遇到了性能问题,那么请获取一些指标,否则请不要担心(此时!)。函数指针表的概念并不是什么新鲜事——它实际上是 C++ 实现虚函数(即 vtable)的方式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-07
        • 1970-01-01
        • 2023-04-04
        • 2013-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多