Algorithm 处理大型RAM工作集的技巧

Algorithm 处理大型RAM工作集的技巧,algorithm,memory-management,Algorithm,Memory Management,我正在开发一个.NET3.5应用程序,专门为一台高性能PC机设计,它可以进行大量的数据处理和计算。我最近遇到一个需要4000 x 5000二维对象数组的问题,它对于32位PC来说非常大,并且会给我一个OutOfMemoryException。避免使用这样的数组的唯一方法是沿着一条充满痛苦和痛苦的非常复杂、耗时的道路走下去 专业人士在处理大型RAM工作集时有什么技巧或技巧吗?您知道有哪些库会对您有所帮助(特别是对于.Net)?有没有办法强制Windows为我的进程分配更多的RAM 编辑: 我使用的

我正在开发一个.NET3.5应用程序,专门为一台高性能PC机设计,它可以进行大量的数据处理和计算。我最近遇到一个需要4000 x 5000二维对象数组的问题,它对于32位PC来说非常大,并且会给我一个OutOfMemoryException。避免使用这样的数组的唯一方法是沿着一条充满痛苦和痛苦的非常复杂、耗时的道路走下去

专业人士在处理大型RAM工作集时有什么技巧或技巧吗?您知道有哪些库会对您有所帮助(特别是对于.Net)?有没有办法强制Windows为我的进程分配更多的RAM

编辑:
我使用的数组将包含大部分空引用,我使用数组跟踪相邻对象。看到它们中的大多数都是空引用,我还假设有一种更有效的方法来跟踪相邻对象,为任何给定对象查找邻居,等等。

好吧,一种想法是为数据库废弃二维数组。类似的东西占用空间小,可以很容易地与应用程序一起部署。甚至还有一种说法


SQLite将从单个文件中读取此数据。因此,磁盘的读写操作可能会影响性能。尽管性能损失的程度可能取决于应用程序的性质。例如,通过索引进行查找应该是快速的。但整个数据库中的大规模计算肯定会更慢。所以我不知道,但也许值得考虑。

从你的评论来看,我想我现在可以回答你的问题了。如果大多数引用为null,那么可以将键散列到一个表中,该表反过来指向元素。散列映射中有恒定的O(1)循环时间,您不必担心密钥冲突,因为每个[x,y]对都是唯一的。您也不必担心内存冲突,因为大多数引用都是空的。

数组是否已修复?i、 e.数组中的值不会更改…将数组内容转储到磁盘并使用内存映射技术可能是值得的,然后您可以将转储数组的一部分加载到内存映射中进行读取…否则,如果数组中的数据和元素发生更改,则不会这样做

只是我的20美分

希望这有帮助, 顺致敬意,
Tom.

在操作系统或流程级别,有两个“简单”的方向

  • 添加到您的 boot.ini和。您可以立即获得额外的1G虚拟地址空间,但不能没有。好 很可能这是你的正确选择 你
  • 问题往往不是这样 缺乏记忆,但是 它的碎片-似乎也与您的上下文相关 (巨大的连续阵列)。一会儿 回到过去,我已经把战斗放在网上了 本机代码的碎片-应至少部分适用于托管代码

  • 您可以高效地存储网格状结构,其中稀疏数组中的大多数元素为空。它们可以以不同的方式实现,但通常对行和列使用修改的链表。对这个主题有一个很好的介绍。

    如果大多数元素都是空的,那么可能根本不需要创建数组

    Jon提出了一种可行的方法——使用链表实现稀疏数组。还有一个:

    public struct CellLocation
    {
       int Row;
       int Column;
    }
    
    public class Element
    {
       public Element(int row, int column)
       {
          Location = new CellLocation {Row = row, Column=column};
       }
    
       public readonly Location { get; private set; }
    
       // your class's other properties and methods go here
    }
    
    现在,您可以将
    元素
    对象存储在
    字典
    中。事实上,我已经将该字典放入了它自己的类中,这样它就可以实现如下方法:

    public IEnumerable<Element> AdjacentElements(Element elm)
    {
       for (int row = -1; row <= 1; row++)
       {
          for (int column = -1; column <= 1; column++)
          {
             // elm isn't adjacent to itself
             if (row == 0 && column == 0)
             {
                continue;
             }
             CellLocation key = new CellLocation { 
                Row=elm.Location.Row + row, 
                Column=elm.Location.Column + column 
             };
             if (!Cells.ContainsKey(key))
             {
                continue;
             }
             yield return Cells[key];
          }
       }
    }
    
    公共IEnumerable邻接元素(元素elm)
    {
    
    对于(int row=-1;row看起来您实际上在做的是一个邻接矩阵。如果是这种情况,并且基础图是稀疏的,那么最好切换到邻接列表。

    数组中的每个元素有多大?这是一个非常重要的数字。数组稀疏吗?每个元素都是引用类型,这是我假设它非常小。而且大多数元素都是空值,现在我说这听起来像是一种巨大的浪费。但它确实需要组织在一个网格状的结构中。它们都引用了什么吗?对象有多大?数组有多满?(有多少个有效引用)你知道32位操作系统的极限很快就达到了:,对吧?我对数据库不是很有经验,但我能弄明白。我用数组跟踪相邻的对象;这很容易(而且高效)吗用数据库做这类事情?是的,绝对可以。数据库引擎能够为您的数据编制索引。该索引提供了一种超快速的查找记录的方法,即使记录存储在文件系统中。这里有一个速度比较页面,描述了使用SQLite的几种情况……为什么人们会这样做认为RDBMS是解决一切问题的解决方案吗?@Nick-我当然不认为。这只是我的第一个想法,因为它具有大幅减少内存消耗的优势。如果使用类似于通用字典的工具,您能够减少足够的内存消耗,使应用程序可用,那么这可能是更好的解决方案。@Nick-在我们发现数组中的大多数元素都为空之前,我也回答了这个问题。但是内存映射仍然占用地址空间,因此在32位上仍然被限制为2-4 GB。@dsimcha:是的,但是您可以指定其中的一部分加载到内存中。我想您的意思是他不必担心密钥不是唯一的e、 他仍然需要担心哈希表中的冲突。如果你走这条路线,我会在这里查看Generic Dictionary类:它在幕后使用哈希表,因此查找应该很快。而且因为它是泛型的,所以你可以同时强式键入键和值。你需要重写CellLocation.GetHashCode(),我想。