【问题标题】:Fast memoization with tuples使用元组快速记忆
【发布时间】:2020-04-27 11:49:39
【问题描述】:

我想使用 memoization 来加速看起来类似于(只有少数可能的参数值被调用)的代码:

double MyFun(double a,double b,int c,char d)
{
    double a = cpu_intensive_pure_function_1(a,c,d);
    double b = cpu_intensive_pure_function_2(b,c,d);
    return a+b;
}

一种可能性是将 args 包装到 Tuple 对象中并使用 Dictionary(新版本的 Dotnet 已为您完成元组散列)

Dictionary<Tuple<double,double,int,char>,double> MyFunCache = new Dictionary<Tuple<double,double,int,char>,double> ();
double MyFun(double a,double b,int c,char d)
{
    var tmp = Tuple<double,double,int,char>(a,b,c,d);
    if(MyFunCache.ContainsKey(tmp))
    {
         return MyFunCache[tmp];
    }

    double a = cpu_intensive_pure_function_1(a,c,d);
    double b = cpu_intensive_pure_function_2(b,c,d);
    return a+b;
}

但这需要在每次调用函数时创建一个 Tuple 对象,这似乎很浪费,难道没有更好的方法吗?有什么东西已经在争论了吗?

【问题讨论】:

  • 我相信您已经在使用一种非常有效(且可读)的方式。与“CPU 密集型功能”相比,分配和比较元组对性能的影响应该可以忽略不计。
  • @TripleAccretion 虽然“缓存”是有效的通用术语,但此问题中描述的纯函数的特殊情况通常称为"memoization"。此外,Tuple 比较的实现本身应该已经在处理哈希冲突,所以这应该不是问题。
  • 如果您使用ValueTuple,那么您将不会受到内存分配的影响。
  • 另一件事:它确实有助于分析受影响的功能,看看某些操作是否具有可衡量的性能影响。只有当这种影响很大时,才需要进行优化。
  • 这个词是memoization,不是memorization

标签: c# tuples memoization


【解决方案1】:

您可以改用ValueTuple。此外,请记住在获得计算值后更新缓存:

Dictionary<(double,double,int,char) ,double> MyFunCache = new Dictionary<(double,double,int,char) ,double> ();
double MyFun(double a,double b,int c,char d)
{
    var key = (a,b,c,d);
    if(MyFunCache.TryGetValue(key, out var cachedResult))
    {
         return cachedResult;
    }

    double a = cpu_intensive_pure_function_1(a,c,d);
    double b = cpu_intensive_pure_function_2(b,c,d);

    MyFunCache.Add(key, a+ b);
    return a+b;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-28
    • 2021-04-28
    • 2019-01-14
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 1970-01-01
    • 2014-09-11
    相关资源
    最近更新 更多