c++ - 缓存重复输入数据的表达式评估

标签 c++ caching numeric

我有几个简单的“表达式”类派生自

namespace Expression {
class Virtual {
  public:
  Virtual();
  ~Virtual();

  virtual
  double eval(double x, double y, double z) const = 0; 
}
}

例如

class MyFun: public Virtual {
  public:
  MyFun();
  ~MyFun();

  virtual
  double eval(double x, double y, double z) const
  {
      return sin(x*x) + exp(z)*y + 3.0; // some expensive expression
  } 
}

这些表达式在许多但非常具体的 xyz 中被求值,即网格的节点

class MyMesh {
  MyMesh();
  ~MyMesh();

  virtual
  std::vector<std::vector<double> > getNodes() const
  {
      return allMyNodes_;
  } 
}

被调用者将实例化一个网格,实例化一个Expression,然后继续执行一些数值过程,其中可能多次在网格节点中评估Expression

MyMesh myMesh();
MyFun myExpr();

Result result = numericalProcedure(myMesh, myExpr);
// [...]

因为 eval 很昂贵,所以我考虑了如何加快速度。想到的是缓存。

一个想法是将所有 eval 结果存储在一个带有一些索引的 vector 中的所有网格节点中,我想知道如何最好地实现这一点。我不想在 Expression 中粘贴任何网格数据(以将缓存保留在那里),也不想让被调用者的界面变得更复杂。

是否有适合此用例的缓存设计模式?将缓存逻辑与其余代码隔离的方法有哪些?

最佳答案

您可以在仿函数中存储从参数数组到结果的映射:

class MyFun {
public:
    virtual
    double eval(double x, double y, double z) const
    {
        std::array<double,3> arr {x,y,z};

        //is the answer cached?
        if (cache_.count(arr))
        {
            return cache_[arr];
        }

        double ret = sin(x*x) + exp(z)*y + 3.0;
        //cache the result
        cache_[arr] = ret;
        return ret;
    } 

private:
    //need mutable so it can be modified by a const function
    mutable std::map<std::array<double,3>, double> cache_;
};

您甚至可以在基类中进行缓存,然后将求值转发给虚函数:

class BaseFun {
public:
    double eval(double x, double y, double z) const
    {
        std::array<double,3> arr {x,y,z};
        if (cache_.count(arr))
        {
            return cache_[arr];
        }

        double ret = doEval(x,y,z);
        cache_[arr] = ret;
        return ret;
    }   

protected:
    virtual double doEval (double x, double y, double z) const = 0;
private:
    mutable std::map<std::array<double,3>, double> cache_;
};

class MyFun : public BaseFun {
private:
    virtual double doEval (double x, double y, double z) const override
    {
        return sin(x*x) + exp(z)*y + 3.0;
    }
};

关于c++ - 缓存重复输入数据的表达式评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30503525/

相关文章:

c++ - 函数的多重定义

c++ - 在 for 循环中将结构传递给 pthread 的正确方法

java - Spring分别缓存列表中的所有元素

caching - channel 并发保证

haskell - 浮点到带有可选小数点的字符串

ruby - is_numeric 消除 Ruby 中的负数

powershell - 在 Powershell 中执行以数值开头的 $PATH 中的 EXE?

c++ - Windows:更改 Exe 的 DLL 搜索顺序

c++ - 在 .pro 文件中强制 32 位程序

c++ - 为 make/g++ 缓存头文件