处理“非常非常”的大型阵列

罗南·蒂博道

我需要处理非常大的小型数组(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] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

处理大型阵列或大型表的最佳方法

来自分类Dev

非常简单的信号处理

来自分类Dev

处理错误非常无聊

来自分类Dev

非常简单的信号处理

来自分类Dev

EclipseLink批处理插入非常非常慢

来自分类Dev

大型同位素馆非常慢

来自分类Dev

覆盖阵列中图像的非常坐标

来自分类Dev

并行处理非常紧密的循环

来自分类Dev

处理非常大的数字

来自分类Dev

NSDate处理非常占用CPU

来自分类Dev

与IN相比,大型OR过滤器的执行速度非常慢

来自分类Dev

需要一个非常定制的大型Winforms网格

来自分类Dev

SQL Server JOIN对大型表的执行非常缓慢

来自分类Dev

使用SimpleXMLElement的大型PHP for循环非常慢:内存问题?

来自分类Dev

在大型表上执行.import时,SQLite非常慢

来自分类Dev

弹性搜索在大型数据集上的排序非常慢

来自分类Dev

在R中解析大型XML文件非常慢

来自分类Dev

Django values_list 在大型数据集上非常慢

来自分类Dev

如何在numpy的阵列非常小的数字设为零?

来自分类Dev

SSD和RAID阵列之间的文件传输非常慢

来自分类Dev

使用Arduino进行非常基本的图像处理

来自分类Dev

处理非常大的Matlab文件

来自分类Dev

关于Java数组处理的非常基本的查询

来自分类Dev

处理动画非常不稳定

来自分类Dev

Pandas 数据帧处理非常慢

来自分类Dev

非常重的 .PDF 文件。如何处理?

来自分类Dev

如何使用WebGL处理和更新大型阵列?

来自分类Dev

处理大型C阵列时出现内存问题

来自分类Dev

使用C ++ AMP处理大型阵列(65536+个元素)