代码之家  ›  专栏  ›  技术社区  ›  fortran

C中运行时的“inlining”(一种)函数

  •  5
  • fortran  · 技术社区  · 15 年前

    我在考虑一个典型的问题,这个问题非常容易抖动,但是很难用原始的C语言来处理。这个场景是建立一系列的函数指针,这些指针将在运行时“组合”(如数学函数组合)一次,然后调用很多次。

    很明显,这样做涉及许多虚拟调用,这些调用很昂贵,如果有足够多的嵌套函数来完全填充CPU分支预测表,那么性能就会大大下降。

    在Lisp这样的语言中,我可能会处理代码并用函数的实际内容替换“虚拟”调用,然后调用 compile 要有一个优化的版本,但在C中这似乎是非常容易被攻击和出错的,使用C是这个问题的一个要求;-)

    那么,你知道有没有一个标准的,便携的,安全的方法来实现这一点?

    干杯

    3 回复  |  直到 15 年前
        1
  •  6
  •   philant    15 年前

    你可能想看看LLVM。他们有一个库,允许从C中进行代码(以及更多的东西)的JIT,它支持许多平台,它是一个开源项目: http://llvm.org/

        2
  •  1
  •   Joseph Quinsey Taseen    15 年前

    关于消除虚拟函数调用,我有两个建议, 如果 性能所必需的。为了便于说明,假设有一个函数以函数指针为参数:

    void my_algorithm(int (*func)(...), ...)
    {
        /* ... */
    }
    

    假设你知道 提前 函数指针可以接受的所有可能值。例如:

    my_algorithm(func_1, ...);
    //...
    my_algorithm(func_2, ...);
    

    首先将原来的my_algorithm()转换为宏:

    #define MY_ALGORITHM(func, ...)       \
    {                                     \
        /* ... */                         \
    }
    

    然后将我的_algorithm()重写为:

    extern int func_1(...);
    extern int func_2(...);
    
    void my_algorithm(int (*func)(...), ...)
    {
        if (func == func_1)
            MY_ALGORITHM(func_1, ...)
        else if (func == func_2)
            MY_ALGORITHM(func_2, ...)
        else
            assert(0 && "Unexpected function arg to my_algorithm()");
    }
    

    这当然会使编译后的对象文件的大小增加一倍。从表面上看,它只删除一个间接级别。但是,如果func_1和/或func_2是内联的,您可能会获得相当大的加速。

    甚至可以“传递”宏,如:

    #define HYPOT_Y(x) hypot(x, y)
    MY_ALGORITHM(HYPOT_Y, ...);     //assumes y is known
    

    第二个建议是使用x宏对其进行了修改。( http://en.wikipedia.org/wiki/C_preprocessor#X-Macros )不要定义,而是将原始my_algorithm()的主体放在单独的文件my_algorithm.h中。然后将my_algorithm()重写为:

    void my_algorithm(int (*func)(...), ...)
    {
        if (func == func_1)
            #define func func_1
            #include "my_algorithm.h"
            #undef func
        else if (func == func_2)
            #define func func_2
            #include "my_algorithm.h"
            #undef func
        else
            assert(0 && "Unexpected function arg to my_algorithm()");
    }
    

    如果代码超过几十行,我可能会使用x宏。其优点 包括 (没有双关语):

    • 没有难看的反斜杠
    • 更容易调试(例如,回溯和单步执行)。

    这都是标准的C,但相当古老。

        3
  •  0
  •   SK-logic    15 年前

    如果您只支持x86,可以尝试嵌入tcc:

    http://bellard.org/tcc/

    推荐文章