跟踪是否已使用哈希表计算结果

时间:2009-08-17 02:33:10

标签: c caching hashtable lookup

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

密集矩阵:

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),则搜索(A->条目,B)将检索C.如果另一方面,特定操作数不在列表中,则会与指向结果矩阵的指针一起添加。

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

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

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

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

(d)什么是跟踪所有创建的对象以便可以正确释放的最好方法?

(e)什么公开的图书馆(c)适合实施这样的东西?

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

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

3 个答案:

答案 0 :(得分:1)

你必须非常小心哈希。如果您有碰撞(不同原始值的哈希值相同),您可能会得到错误的结果。 你确定计算矩阵的散列比执行实际操作更有效(这一切都取决于这些操作的数量/复杂性)

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

答案 1 :(得分:0)

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

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

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

  1. 对于非常小的矩阵或列/行向量,完整计算与计算散列的边际开销很小......因此,除非您进行如此多的计算,否则缓存几乎不会产生额外的好处及时积累足以发挥作用。
  2. 对于非常大的矩阵,如果可能的输入矩阵非常有限,则可能会看到缓存带来的好处。如果它们可以是任何东西,那么可能的好处就是在缓存上重复攻击的罕见性,以及管理缓存的内存成本和复杂性。
  3. 缓存会加速结果,但只能在非常有限的情况下使用。

    鉴于您已经征求了关于库的建议,这听起来像是过早优化的情况。我将实现您的程序而不进行缓存,性能配置文件,如果您在阵列算术中发现性能瓶颈,然后考虑优化数字运算的方法。

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

答案 2 :(得分:0)

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

本文还提到了一些可以帮助您的图书馆。