【问题标题】:How to have a huge list? Greather than 2 GiB?如何拥有庞大的清单?大于 2 GiB?
【发布时间】:2011-10-10 22:31:53
【问题描述】:

在 .Net 框架中,2 GiB 是您可以为对象分配的最高内存。这个事实与平台(x64 或 x86 或 ...)独立。 我需要一个包含超过 2^30 个复数(每个是 16 个字节)的巨大列表。

注意:

与 32 位 Windows 操作系统一样,有 2GB 的限制 在运行 64 位托管时可以创建的对象的大小 64 位 Windows 操作系统上的应用程序。

来自http://msdn.microsoft.com/en-us/library/ms241064%28VS.80%29.aspx

【问题讨论】:

  • 您需要一个占用超过 17.18 GB RAM 的对象?除非你有一些很棒的服务器,否则你可能需要考虑一种不同的方式来做到这一点。
  • @Ben 为什么?我的桌面上还有更多...
  • 我希望你的数字是值类型(结构)而不是引用类型(类)...否则你的内存使用会膨胀。
  • @xanatos,LuKe H:谢谢。由于 Visual Studio 的愚蠢,我错了:D。解决方案平台可能在其项目中有所不同。我的 HugeArray 在其他以 x86 模式编译的项目中。

标签: .net memory-management


【解决方案1】:

然后您需要以其他方式对其进行封装 - 创建您自己的集合,该集合可以处理足够的数据,并且可能会使用long 而不是int 作为索引值,等等,通过在内部委托较小的集合。我怀疑这不会很有趣,但我看不出你还有很多其他选择。

从根本上说,任何由单个数组支持的东西都会遇到问题。

【讨论】:

    【解决方案2】:

    改为锯齿状; Complex[][] 例如。如果需要,它可以是宽矩形锯齿状,只需始终对内部数组使用相同的大小。

    另一种选择;使用大列表的链表;这具有更容易扩展的优点。

    【讨论】:

      【解决方案3】:

      我会实现一个在内部使用多个数组的包装类。

      类似于以下内容:

      void Main()
      {
          long count=3*1024*1024;
          var arr=new LargeArray<Complex>(count,12);
          for(long i=0;i<count;i++)
          {
            arr[i]=new Complex(i,-i);
          }
          for(long i=0;i<count;i++)
          {
            if(arr[i].R!=i)
              throw new Exception("Fail"+i+" "+arr[i].R);
          }
      }
      
      struct Complex
      {
        public double R,I;
      
        public Complex(double r,double i)
          {
            R=r;
            I=i;
          }
      }
      
      
      class LargeArray<T>
      {
        private readonly int partBits;  
        private readonly long size;
      
        private T[][] data;
      
        public T this[long index]
        {
          get
          {
            if((ulong)index>=(ulong)size)
              throw new IndexOutOfRangeException();
            int part=(int)(index>>partBits);
            int subIndex=(int)(index&((1<<partBits)-1));
            return data[part][subIndex];
          }
          set
          {
            if((ulong)index>=(ulong)size)
              throw new ArgumentOutOfRangeException();
            int part=(int)(index>>partBits);
            int subIndex=((int)index&((1<<partBits)-1));
            data[part][subIndex]=value;
          }
        }
      
        public LargeArray(long size,int partBits)
        {
          this.size=size;
          this.partBits=partBits;
          int partSize=1<<partBits;
          int partCount=(int)(((size-1)>>partBits)+1);
          data=new T[partCount][];
          for(int i=0;i<partCount;i++)
            data[i]=new T[partSize];
        }
      }
      

      如果您使用 64 位进程,则它可以超过 2GB。我用 5GB 试了一下,除了将我的电脑换成停止状态外,它还可以工作。

      【讨论】:

      • 小修正:最后一个块可能更小(4个“块”中的9个元素:4、4、1)
      • @salman 在修复了一些小问题后,这段代码在 2GB 以上运行良好。在我的测试中,它处理得很好是分配了 5 GB 的内存。当然,我将它作为 64 位进程运行。所以我看不出你的问题是什么。但既然你确定你的进程是 64 位的,那也不是你的问题。所以我唯一能想到的是你使用了Complex 类而不是Complex 结构。
      • @xanatos 我知道。但这是一个小的优化问题。如果您分配 5GB 的内存,您将不会关心 1MB 或多或少。
      • 通过更改它,您可以删除对 IndexOutOfRangeException 的检查并直接使用数组之一,这可以加快代码速度。然后您将拥有 blogs.msdn.com/b/joshwil/archive/2005/08/10/450202.aspx :-) :-) 只有可配置的块大小
      【解决方案4】:

      在 .NET 4.5 中,数组似乎实际上可以更大 2 GB。对元素数量而不是大小有硬性限制。 http://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx

      谈论新标志和数组的新限制。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-27
        • 1970-01-01
        • 2013-07-26
        • 1970-01-01
        • 2022-08-06
        • 1970-01-01
        • 2022-01-11
        相关资源
        最近更新 更多