类方法子集的惰性评估



我正在寻找一个通用的、懒惰的评估式过程来简化我的代码。

现在,我有能力加快数学函数的执行——前提是我先调用另一个方法来预处理它。更具体地说,给定一个类型的函数:

const Eigen::MatrixXd<double, -1, -1> function_name(const Eigen::MatrixXd<double, -1, -1>& input)

我可以将其传递到另一个函数g中,它将生成一个新版本的function_nameg_p,它可以更快地执行。

我想把所有这些繁忙的工作从最终用户那里抽象出来。理想情况下,我想创建一个类,这样当在任何输入(比如x(上调用任何与function_name的方法签名匹配的函数f时,就会发生以下情况:

  1. 该类检查以前是否调用过f
  2. 如果没有,则调用g(f),然后调用g_p(x)
  3. 如果有,它只调用g_p(x)

这很棘手,原因有两个。首先,我不知道如何获得对当前方法的引用,或者这是否可能,并将其传递给g。也许有办法解决这个问题,但将一个函数传递给另一个对我来说是最简单/最干净的

第二个更大的问题是如何强制调用g。我读过关于execute around模式的文章,它几乎可以用于此目的——除了,除非我理解错了,否则不可能在周围的函数调用中引用f

有什么方法可以干净地实现我的梦想类吗?理想情况下,我希望最终推广到function_name类型之外(也许使用模板(,但可以一步一个脚印。我也对其他解决方案持开放态度,以获得相同的功能。

我认为在C++中不可能有"完美"的解决方案,原因如下。

如果呼叫站点显示:

result = object->f(x);

编译后,它将调用未优化的版本。在这一点上,你几乎被束缚住了,因为C++中没有办法改变函数调用的位置,这是在编译时为静态链接确定的,在运行时通过vtable查找为虚拟(动态(链接确定的。不管是什么情况,这都不是你可以直接改变的。其他语言确实允许这样做,例如Lua,具有讽刺意味的是,C++的曾祖父BCPL也允许这样做。然而C++不允许。

TL;DR要获得一个可行的解决方案,您需要修改被调用的函数,或者每个使用其中一个的调用站点。

长话短说:你需要做两件事中的一件。您可以将问题卸载到被调用的类,并使所有函数看起来像这样:

const <return_type> myclass:f(x)
{
static auto unoptimized = [](x) -> <return_type>
{
// Do the optimizable heavy lifting here;
return whatever;
};
static auto optimized = g(unoptimized);
return optimized(x);
}

然而,我强烈怀疑这正是不想做的事情,因为假设您所说的最终用户是该类的作者,这就无法满足您从最终用户那里卸载该类的要求。

然而,您也可以通过使用模板来解决它,但这需要对您称之为模板的每个地方进行修改。从本质上讲,您将上述逻辑封装在一个模板函数中,将unoptimized替换为裸类成员,并将其他大部分内容单独保留。然后您只需在调用站点调用模板函数,它就可以工作了。

这确实具有呼叫站点相对较小变化的优势:

result = object->f(x);

变为:

result = optimize(object->f, x);

或:

result = optimize(object->f)(x);

这取决于如何设置optimize模板。它还有一个优点是对类没有任何更改。

所以我想归根结底就是你不想做出改变的地方。

还有另一种选择。是否可以选择采用最终用户编写的类,并通过自定义预处理器传递cpph文件?这可以遍历类并自动进行上面概述的更改,这样就可以在调用站点获得不需要更改的优势。

最新更新