高效重新排序大型数据集以最大化内存缓存效率

时间:2009-01-31 21:04:14

标签: algorithm caching graph-theory ram

我一直在研究一个我认为人们可能会感兴趣的问题(也许有人知道一个预先存在的解决方案)。

我有一个大型数据集,包含一长串指向对象的指针,如下所示:

[
  (a8576, b3295), 
  (a7856, b2365), 
  (a3566, b5464),
  ...
]

在任何时候都有太多的对象要保留在内存中(可能是几百GB),所以它们需要存储在磁盘上,但可以缓存在内存中(可能使用LRU缓存)。

我需要在每对中运行此列表处理,这需要将对中的两个对象加载到内存中(如果它们尚未缓存在那里)。

所以,问题是:有没有办法重新排序列表中的对,以最大化内存缓存的有效性(换句话说:最小化缓存未命中数)?

备注

  1. 显然,重新排序算法应该尽可能快,并且不应该依赖于能够一次将整个列表放在内存中(因为我们没有足够的RAM) - 但如果有必要,它可以多次遍历列表。

  2. 如果我们处理单个对象而不是对,那么简单的答案就是对它们进行排序。这显然不适用于这种情况,因为你需要考虑这两个元素。

  3. 问题可能与找到minimum graph cut的问题有关,但即使问题是相同的,我也不认为解决问题的方法是

  4. 我的假设是启发式会将数据从磁盘中流出,并以更好的顺序将其写回块中。它可能需要多次迭代。

  5. 实际上它可能不仅仅是成对,它可能是三胞胎,四胞胎或更多。我希望可以很容易地推广出一对这种配对的算法。

4 个答案:

答案 0 :(得分:1)

首先,您可以mmap列表。如果有足够的地址空间,而不是内存,例如在64位CPU上。这样可以更方便地按顺序访问元素。

您可以根据缓存中考虑两个元素的最小距离对该列表进行排序,如果对象位于连续的空间中,则可以很好地工作。排序函数可以是:compare(a,b)到(c,d)=(a - c)+(b - d)(看起来像汉明距离)。然后拉入对象存储区的切片并根据列表进行处理。

编辑:修正了距离的错误。

答案 1 :(得分:1)

即使您不是只是对此列表进行排序,multiway merge sort的一般模式也可能适用 - 也就是说,考虑集合的某种(可能是递归的)细分可以分别在存储器中处理的较小集合,然后是第二阶段,其中先前处理的集合的小块可以全部组合在一起。即使不知道你对这些对的具体性质,可以肯定的是,当你处理排序数据时(包括图形问题,这可能是你的对象),许多算法问题变得更加直接。这里的手)。

答案 2 :(得分:1)

您的问题与计算机图形硬件类似:

当在三角形网格中渲染索引顶点时,通常硬件具有最近转换顶点的缓存(上次我不得不担心它的大约128,但怀疑这些天数更大)。未缓存的顶点需要相对昂贵的变换操作来计算。用于重构三角形网格以优化缓存使用的“网格优化”曾经是一个非常热门的研究课题。谷歌搜索   顶点缓存优化 (或优化:^)可能会找到一些与您的问题相关的有趣材料。正如其他海报所说,我怀疑这样做有效将取决于利用数据中任何固有的一致性。

要记住的另一件事是:当LRU缓存变得过载时,值得更改为MRU替换策略以至少保留内存中的一些项目(而不是每次传递都转换整个缓存)。我似乎记得John Carmack在Direct3D纹理缓存策略方面写了一些关于这个主题的好材料。

答案 3 :(得分:0)

我认为这个问题的答案很大程度上取决于这对对象的访问模式。正如你所说的那样,只需对一个简单的非配对案例进行排序即可。在一个更复杂的情况下,如果模式对于那些值的位置更重要(例如,如果这些是键/值对并且您正在执行很多搜索,键的位置比值更重要。)

所以,实际上,我的答案是这个问题在一般情况下无法回答。

为了存储你的结构,你真正想要的可能是B-tree。这些是为您所谈论的内容而设计的 - 跟踪您不希望(或不能)将整个内容保留在内存中的大型集合。

相关问题