我正在考虑一个非常JIT能够解决的典型问题,但很难用原始C进行处理。该场景设置了一系列将被“组合”的函数指针(如数学函数组合)一旦在运行时,然后调用很多次。
以明显的方式执行它涉及许多虚拟调用,这些调用很昂贵,如果有足够的嵌套函数来完全填充CPU分支预测表,那么性能会大幅下降。
在像Lisp这样的语言中,我可能会处理代码并用函数的实际内容替换“虚拟”调用,然后调用compile
来获得优化版本,但这看起来非常hacky和错误容易在C中做,并且使用C是这个问题的要求; - )
那么,你知道在C中是否有一种标准,便携和安全的方法来实现这一目标吗?
干杯
答案 0 :(得分:6)
您可能希望查看LLVM。他们有一个允许来自C的JITing代码(以及更多东西)的库,它支持许多平台,它是一个开源项目:http://llvm.org/
答案 1 :(得分:1)
我有两条关于消除虚拟功能调用的建议, if 表现必不可少。为了便于说明,假设您有一个函数指针作为参数的函数:
void my_algorithm(int (*func)(...), ...)
{
/* ... */
}
并且假设您事先知道 函数指针可以采用的所有可能值。例如:
my_algorithm(func_1, ...);
//...
my_algorithm(func_2, ...);
首先将原始my_algorithm()转换为宏:
#define MY_ALGORITHM(func, ...) \
{ \
/* ... */ \
}
然后将my_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)的变体。而不是#define,将原始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.但相当老派。
答案 2 :(得分:0)
如果你只支持x86,你可以尝试嵌入TCC: