c++ - 运行时动态函数解析

标签 c++ templates metaprogramming jit

我的项目在运行时需要加载很多模块,每个模块都包含很多函数,其形式类似于下面的伪代码:

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);
} 

其中ctx.arg[“arg1”]ctx.arg[“arg2”]ctx.arg[“arg3”] > 是在运行时传递给 someFunction 的参数。 someFunction2someFunction3 无法在编译时静态解析,但在运行时加载所有模块时就会知道(它们是否已在其他模块中定义)。

现在,一个简单的实现是使用 HashMap 来存储所有这些函数的函数句柄,但是哈希会很慢,因为通常需要搜索 10k 个函数,并且每个函数都会在其他函数中多次调用(例如:枚举参数以找到将产生所需结果的正确组合)。

因此,我正在寻找某种解决方案,该解决方案将在加载所有模块时对这些“ctx.call”执行一次性替换,而不是每次都执行“散列和探测”。目前主要问题是“替换” Action 。我提出了一些想法,但它们并不完美:

<小时/>

第一个解决方案:创建一个内部函数 inner_func(func_handle1, func_handle2, arg1, arg2, arg3),并使用 std::bind 创建一个外部包装器 outer_wrapper()

问题:对用户不友好,必须明确告诉上下文要查找哪些函数和参数。

<小时/>

第二个解决方案:使用元编程 + constexpr + 宏自动计算函数和参数名称引用,然后创建一个引用表,然后让上下文在运行时填充每个表。

问题:我无法解决,需要一些帮助。我已经阅读了来自 facebook、来自 boost 的 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))

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;
    )
}

然后通过某种方式,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"
    }
}

然后当所有模块加载完毕后,系统会读取func_namearg_name,并填充适当的函数指针和变量指针到functions和分别是args

状态:首先使用 hashmap,完成后我将发布更新。

状态:我自己想出了一个解决方案,还测试了哈希实现,发布在下面。

任何想法将不胜感激。谢谢!

最佳答案

Now, a naive implementation would be using a hash map to store a function handle to all of these functions, but hashing would be slow as there are typically 10k functions to search for [...]

哈希表的查找成本O(1)。您是否尝试过这种广泛使用的解决方案来解决这个问题并进行了性能分析?您是否尝试过使用不同的哈希算法来减少哈希时间和冲突?

关于c++ - 运行时动态函数解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60015568/

相关文章:

c++ - 关于 C++ 中默认构造函数的奇怪编译器行为

c++ - 使用 auto 声明 block

c++ - 将 100 个类数据成员初始化为零

c++ - 使用 boost::numeric_cast<>

python - 列出 Python 中函数期望的变量?

c++ - 引用模板参数的用途

javascript - 有哪些非常有用的社交网站 JQuery 插件?

C++ 继承 : Calling subclass function of template

c++ - hana::second 无法推断类型

Ruby:define_method 与 def