【问题标题】:tracking if a result has already been computed using hash table跟踪是否已经使用哈希表计算了结果
【发布时间】:2009-08-17 02:33:09
【问题描述】:

我的应用程序将对密集矩阵执行大量矩阵运算(例如,加法/乘法)。我想缓存唯一的结果以避免重复计算。

密集矩阵:

typdef struct denseMatrix{
 int m;
 int n;
 double **d;            // actual matrix
 multiplyTable **entry; // key & result
} dns; 

表格条目:

typedef struct multiplyTable{
 dns *rightOperand; // key
 dns *result;       // value
} multiplyTable;   // or something like that

dns *A, *B, *C, *D...; // allocated internally

C = mult(A,B); //may be called many many times. 

在这种情况下,mult 将向表中添加一个条目(操作数,结果)对

add(A->entry, B, C); //B is the right operand and C is the result

稍后如果再次调用 D = mult(A, B),search(A->entry,B) 将检索 C。另一方面,如果特定操作数不在列表中,则为与指向结果矩阵的指针一起添加。

我以前从未做过这样的事情,我什至不确定这是否是解决问题的方法。根据我有限的理解,哈希表可以用来实现这样的东西。

我遇到的实际问题包括: (a) 哈希表首先是解决问题的适当方法吗?他们允许指针地址作为键和值吗??

(b) 将“哈希表”作为“字段”保留在结构中是否有意义?这样,我已经有了左操作数,我只需要在乘法表中搜索右操作数。或者,是否应该有一个独立的表,左右操作数都作为键?

(c) 我应该为加法/乘法等创建单独的表,还是应该有一个带有操作数和运算符的表?

(d) 跟踪所有创建的对象以便适当释放这些对象的最佳方法是什么??

(e) 哪些公开可用的库(在 c 中)适合实现这样的功能?

我正在寻求有关 (a) 解决问题的替代方法以及 (b) 此类替代方法的优点/缺点的意见/建议。

最后,我发现这个论坛非常有帮助,并想表达我的感激之情。 ++谢谢。

【问题讨论】:

    标签: c caching hashtable lookup


    【解决方案1】:

    你必须非常小心哈希。如果您有冲突(不同原始值的哈希值相同),您最终可能会得到错误的结果。 您确定计算矩阵的哈希会比执行实际操作更有效吗(显然这完全取决于这些操作的数量/复杂性)

    第二个问题 - 你没有提到你的缓存驱逐政策。你打算只添加到哈希表而不删除吗?根据不同矩阵的数量,您可能会耗尽内存...

    【讨论】:

    • 感谢您的快速回复。这两个是关键问题。 (a) 时间:我假设即使是一个小矩阵(4 x 4)的矩阵矩阵乘法也会比计算散列函数更昂贵。 (b) 空间:我假设在哈希表中存储条目的开销将小于存储同一 matix 的多个副本。这些假设合理吗?我真的不知道哈希表的空间/时间开销。 “最小完美哈希”是否合适?
    • 我忘了说,一旦创建了同一套操作,就会重复很多次。 N0 额外的添加将在生命周期中发生。因此,进入表的成本将分布在许多复制中。唯一的成本将是搜索操作数 + 检索和更新结果。
    • 正确,哈希值显然比矩阵本身占用更少的空间。顺便说一句,这里有一些不错的 cmets:stackoverflow.com/questions/934827/hash-function-to-matrix
    【解决方案2】:

    首先回答简单的部分:对于矩阵运算的 C++ 库,请查看 newmat,它具有大量内置功能,并且在性能方面非常高效。

    对于您构建散列以加速计算的特定情况 - 除非您要在非常有限的一组矩阵上执行操作,否则缓存才是值得的。要为矩阵构建唯一哈希,您需要访问每个条目 - 并根据每个条目的位置和值计算哈希。更糟糕的是,矩阵并不总是可交换的,例如AB != BA 特殊情况除外。

    这意味着您的缓存必须为每个特定计算存储一个条目。因此,除非您处理的输入矩阵范围非常小,否则保存所有结果的内存成本将非常巨大。

    1. 对于非常小的矩阵或列/行向量,完整计算与计算散列的边际开销很小...因此缓存将提供很少的额外好处,除非您执行的计算量只有几分之一毫秒的差异时间会积累到足以产生影响。
    2. 对于非常大的矩阵,如果可能的输入矩阵非常有限,您可能会看到缓存的好处。如果它们可以是任何东西,那么可能的好处会被缓存重复攻击的罕见性以及管理缓存的内存成本和复杂性所抵消。

    缓存会加速结果,但仅限于非常有限的情况。

    鉴于您也向图书馆寻求建议,这听起来像是过早优化的情况。我会在不使用缓存的情况下实现您的程序,对其进行性能分析,并且如果您在数组算法中发现性能瓶颈,然后考虑优化数字运算的方法。

    编辑:关于计算哈希:如果您有一个 n×m 矩阵 X,那么计算该矩阵的哈希至少与操作 RXC 一样复杂,其中 R是行向量 [1,..,n],C 是列向量 [1,..,m]。我还没有计算出最佳收益,但对于 2x2、3x3 量级的非常小的矩阵,进行原始计算将比计算哈希更便宜。

    【讨论】:

    • 好点。是的,与重复计算的数量相比,不同矩阵的总数将非常少。我会试一试,看看它对不同大小的矩阵和不同计算的数量有多大的影响。我对您的最后评论很感兴趣,我只是想使用指向 rightOperand 矩阵的指针作为键,使用指向结果矩阵的指针作为值。可以将指针用作键 - 将其视为int??谢谢。
    【解决方案3】:

    此功能称为 memoization - 有关详细信息,请参阅wikipedia 文章。

    本文还提到了一些可以帮助您的库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-19
      • 2010-12-02
      • 2014-06-16
      • 2021-07-13
      • 2016-06-23
      • 1970-01-01
      • 2012-07-19
      相关资源
      最近更新 更多