Iff*_*ffi 3 c++ templates jit metaprogramming
我的项目在运行时需要加载很多模块,每个模块都包含很多函数,形式类似于下面的伪代码:
void someFunction(Context &ctx) {
bool result;
result = ctx.call("someFunction2")(ctx.arg["arg1"], ctx.arg["arg2"])
&& ctx.call("someFunction3")(ctx.arg["arg1"], ctx.arg["arg3"]);
ctx.result(result);
}
Run Code Online (Sandbox Code Playgroud)
其中ctx.arg["arg1"],ctx.arg["arg2"],ctx.arg["arg3"]是传递到的参数someFunction在运行时。someFunction2并且someFunction3无法在编译时静态解析,但会在运行时在加载所有模块时知道(它们是否已在其他模块中定义)。
现在,一个简单的实现将使用散列映射来存储所有这些函数的函数句柄,但散列会很慢,因为通常需要搜索 10k 个函数,并且每个函数将在其他函数中被多次调用(例如:枚举参数以找到将产生所需结果的正确组合)。
因此,我正在寻找某种解决方案,它会在加载所有模块时对这些“ctx.call”执行一次替换,而不是每次都执行“散列和探测”。目前的主要问题是“替换”操作。我提出了一些想法,但它们并不完美:
第一个解决方案:创建一个内部函数inner_func(func_handle1, func_handle2, arg1, arg2, arg3),并用于std::bind创建一个外部包装器outer_wrapper()。
问题:不是用户友好的,必须明确告诉上下文要查找哪些函数和参数。
第二种解决方案:使用元编程+ constexpr + 宏来自动统计函数和参数名称的引用,然后创建一个引用表,然后让上下文在运行时填充每个表。
问题:我无法解决,需要一些帮助。我已经阅读了来自 facebook、mpl 和 hana 的 Fatal 库的文档,但似乎没有一种干净的方法可以做到这一点。
第三种解决方案:使用 JIT 编译器
问题:c++ JIT 编译器的选择是有限的。NativeJIT 不够强大,easy::JIT 似乎不能定制,也不容易分发。asmjit 不可用。
PS:问题上下文是“自动规划器”,这些函数是用来构造谓词的。Context ctx只是一个例子,如果需要,您可以使用其他合适的语法,只要它们易于用于表示以下 lisp 表达式:
(and (at ?p ?c1)
(aircraft ?a)
(at ?a ?c3)
(different ?c1 ?c3))
Run Code Online (Sandbox Code Playgroud)
PPS:更具体地说,我正在考虑这样的事情:
用户将定义一个如下所示的函数:
void module_init() {
FUNC ("someFunction")("p", "a", "c1", "c3") (
bool result;
result = CALL("at")("p", "c1")
&& CALL("aircraft")("a")
&& CALL("at")("a", "c3")
&& CALL("different")("c1", "c3")
/// Users should also be able to access arguments as a "Variable"
/// class using ARG["p"]
return result;
)
}
Run Code Online (Sandbox Code Playgroud)
然后通过某种方式,FUNC()将转换为类似于以下内容的函子:
struct func_someFunction {
some_vector<std::function<bool()>> functions;
some_vector<Variable*> args;
some_vector<std::string> func_name;
some_vector<std::string> arg_name;
bool operator()() {
/// above representation of Func(), but function and args are pointers in "functions" and "args"
}
}
Run Code Online (Sandbox Code Playgroud)
然后当所有模块加载完毕后,系统将读取func_name和arg_name,并分别填充相应的函数指针和变量指针到functions和args。
状态:首先使用hashmap,完成后我会发布更新。
状态:自己想出了一个解决方案,也测试了哈希实现,发布在下面。
任何想法将不胜感激。谢谢!
现在,一个简单的实现将使用散列映射来存储所有这些函数的函数句柄,但散列会很慢,因为通常有 10k 个函数要搜索 [...]
哈希表的查找成本为O(1)。您是否尝试过这种广泛使用的解决方案并进行了性能分析?您是否尝试过使用不同的散列算法来减少散列时间和冲突?