最小化大负荷数的算法

时间:2013-08-26 14:47:30

标签: algorithm caching language-agnostic

我有一个算法,我需要计算大对象之间的所有成对距离(其中距离是真正的度量,所以dist(a,b) == dist(b,a),在所有其他度量要求中)。我有大约一千个物体,所以我需要计算大约500,000个距离。有几个问题:

  1. 所有这1000个对象都是序列化的,位于磁盘上的单个文件中。
  2. 与相对琐碎的距离计算相比,从磁盘读取它们是一项巨大的操作。
  3. 我无法在没有交换的情况下同时将所有内容都放在内存中,然后捶打。我一次可以在内存中容纳大约500个。
  4. 这意味着在某些时候我需要在读取并释放内存之前将对象重新读入内存。
  5. 因此,考虑到从磁盘读取是瓶颈,并且我一次不能读取超过一半的数据,是否有人会想到一个读取和释放这些对象的算法,这会最大限度地减少读取总数?

    我考虑在上半场阅读,完成所有这些成对距离,释放所有内存并读取后半部分,然后完成所有这些成对距离。此时,我仍然需要前半部分中的对象与第二部分中的对象之间的距离,我不知道该怎么做。我还考虑过一个缓存,当它满了时,随机选择一个当前对象来驱逐并读取下一个,但我觉得必须有一个更好的选择。我考虑过像LRU这样的东西,但它可能会导致在最后一次计算中所需对象被驱逐的行为。

    总而言之,我有点卡住了。有什么建议吗?

3 个答案:

答案 0 :(得分:3)

加载前半部分。计算成对距离。将前半部分保留在内存中,逐个加载后半部分,计算距离。加载整个后半部分并计算成对距离。这大约是每点1.5次读取,这在以下模型中是最佳的。

模型是这个任务的语法正确的程序是LOAD( i j )形式的指令序列,其含义是加载点< em> i 进入内存位置 j 。如果对于每对点,在两个点都在内存中之后立即存在指令,则该程序是正确的。

很明显,在正确的程序中,每个点至少加载一次。假设恰好有1000个点和500个位置,那么至少有500次驱逐有利于第一次加载点。假设不失一般性,在内存中没有任何重复点。在点 p 被驱逐以支持首次加载点 q 之后,需要重新加载 p 以便要计算的 p q 之间的距离。因此,至少有500次重新加载,因此至少有1500次加载。

答案 1 :(得分:2)

我的第一个想法(所以它可能不是最好的一个):

每个i:

  • 读取第i组250.计算它们之间的距离。

  • 对于每个剩余的组j为250:

    • 阅读第j组。

    • 计算第i组和第j组中各点之间的距离。

    • 弃掉小组j。

  • 弃掉小组i。

所以你读了以下几组:

i  j
1  2
   3
   4
2  3
   4
3  4
4

你会注意到阅读第4组本身是没有意义的 - 你可以在阅读第3组(或其他组)时计算距离。

所以你以每点平均(1+2+3+3)/4 = 2.25个读数结束。

答案 2 :(得分:1)

我会尝试略微提高@Dukeling的答案。如果我理解正确,这将更好

i j
1 2
  3
  4
2 
3
  2

现在每点有(1 + 3 + 2 + 1)/4=1.75次读取。