我需要处理非常大的小型数组(int或float数组),我仅将X64定位在具有大量RAM的计算机上,在我的方案中,物理内存从来不是问题。在查看gcAllowVeryLargeObjects的文档时,我注意到了这一点:
•对于字节数组和单字节结构数组,任何单个维的最大索引为2,147,483,591(0x7FFFFFC7),对于其他类型,最大索引为2,146,435,071(0X7FEFFFFF)。
现在我的问题是我实际上“需要”使用更大的数组,这里合适的解决方法是什么?创建数组或其他抽象的数组?
知道我最需要顺序访问这些数组(永远不要随机读取,但是通常不同的段会被不同的线程(可能一次有100个以上的线程)依次读取),我最好的选择是什么?
我可能需要容纳最多65 536 000 000个或更多的数组。
如果确实必须打破数组长度限制,则必须将数组拆分为适当大小的块。您可以将这些块包装在具有适当语义的容器中,例如James McCaffrey不久前在博客中写道的BigArrayOfLong对象。有很多其他喜欢它的人。
基本思想是使用锯齿状数组分配要使用的空间。请注意,多维数组不会给您任何好处,因为它仍然是单个对象,而锯齿状数组是较小的数组数组,每个数组都是(可能不是连续的)内存中的自己的对象。
这是一个非常简单的(不是最佳的)实现:
public class HugeArray<T> : IEnumerable<T>
where T : struct
{
public static int arysize = (Int32.MaxValue >> 4) / Marshal.SizeOf<T>();
public readonly long Capacity;
private readonly T[][] content;
public T this[long index]
{
get
{
if (index < 0 || index >= Capacity)
throw new IndexOutOfRangeException();
int chunk = (int)(index / arysize);
int offset = (int)(index % arysize);
return content[chunk][offset];
}
set
{
if (index < 0 || index >= Capacity)
throw new IndexOutOfRangeException();
int chunk = (int)(index / arysize);
int offset = (int)(index % arysize);
content[chunk][offset] = value;
}
}
public HugeArray(long capacity)
{
Capacity = capacity;
int nChunks = (int)(capacity / arysize);
int nRemainder = (int)(capacity % arysize);
if (nRemainder == 0)
content = new T[nChunks][];
else
content = new T[nChunks + 1][];
for (int i = 0; i < nChunks; i++)
content[i] = new T[arysize];
if (nRemainder > 0)
content[content.Length - 1] = new T[nRemainder];
}
public IEnumerator<T> GetEnumerator()
{
return content.SelectMany(c => c).GetEnumerator();
}
IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
这是静态分配的,但要使其增长以适应需求并不难。只要确保您指定的块大小不完全超出范围即可。为了防万一,我已经根据商品尺寸进行了计算。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句