大型多维数组(锯齿数组)C#的解决方法?

大型多维数组(锯齿数组)C#的解决方法?,c#,arrays,memory,multidimensional-array,jagged-arrays,C#,Arrays,Memory,Multidimensional Array,Jagged Arrays,我正在尝试初始化三维数组以加载体素世界 地图的总大小应为(2048/1024/2048)。我试图初始化“int”的锯齿状数组,但引发了内存异常。尺寸限制是多少? 我的表格大小:2048*1024*2048=4'191'893'824 有人知道解决这个问题的方法吗 // System.OutOfMemoryException here ! int[][][] matrice = CreateJaggedArray<int[][][]>(2048,1024,2048); // if i

我正在尝试初始化三维数组以加载体素世界

地图的总大小应为(2048/1024/2048)。我试图初始化“int”的锯齿状数组,但引发了内存异常。尺寸限制是多少? 我的表格大小:2048*1024*2048=4'191'893'824

有人知道解决这个问题的方法吗

// System.OutOfMemoryException here !
int[][][] matrice = CreateJaggedArray<int[][][]>(2048,1024,2048);
// if i try normal Initialization I also throws the exception
int[, ,] matrice = new int[2048,1024,2048];

    static T CreateJaggedArray<T>(params int[] lengths)
    {
        return (T)InitializeJaggedArray(typeof(T).GetElementType(), 0, lengths);
    }

    static object InitializeJaggedArray(Type type, int index, int[] lengths)
    {
        Array array = Array.CreateInstance(type, lengths[index]);
        Type elementType = type.GetElementType();

        if (elementType != null)
        {
            for (int i = 0; i < lengths[index]; i++)
            {
                array.SetValue(
                    InitializeJaggedArray(elementType, index + 1, lengths), i);
            }
        }

        return array;
    }
//System.OutOfMemoryException在这里!
int[][]matrice=CreateJaggedArray(204810242048);
//如果我尝试正常初始化,我也会抛出异常
整数[,]矩阵=新整数[204810242048];
静态T CreateJaggedArray(参数int[]长度)
{
return(T)InitializeJaggedArray(typeof(T).GetElementType(),0,length);
}
静态对象初始化JaggeDarray(类型类型,int索引,int[]长度)
{
Array数组=Array.CreateInstance(类型,长度[索引]);
Type elementType=Type.GetElementType();
if(elementType!=null)
{
对于(int i=0;i
C#中单个对象的最大大小为2GB。由于您创建的是多维数组而不是锯齿状数组(不管方法的名称如何),因此需要包含所有这些项而不是几个项的是单个对象。如果您实际使用的是锯齿状数组,那么您就不会有一个包含所有数据的项目(即使总内存占用空间会稍微大一点,而不是小一点,它只是分布得更多)。

来自(重点添加)

默认情况下,阵列的最大大小为2 GB。在一个 在64位环境中,您可以通过设置 gcAllowVeryLargeObjects配置元素的enabled属性 在运行时环境中为true。但是,该数组仍将是 限制为总共40亿个元素,最大索引为 任意给定维度中的0x7FFFFF(0X7FFFFFC7用于字节数组和 单字节结构的数组)

因此,尽管有上述答案,即使您将标志设置为允许更大的对象大小,数组仍然限制为32位元素数限制

编辑:您可能需要重新设计,以消除当前使用多维数组时对多维数组的需要(正如其他人所建议的,在使用实际的交错数组或其他维度集合之间,有几种方法可以做到这一点)。考虑到元素数量的规模,最好使用动态分配所用对象/内存的设计,而不是必须预先分配对象/内存的数组。(除非您不介意使用很多GB的内存)EDITx2:也就是说,您可以定义定义填充内容的数据结构,而不是定义世界上所有可能的体素,甚至是“空”体素。(我假设绝大多数体素是“空的”而不是“填充的”)


编辑:虽然不是琐碎的,特别是如果大部分空间被认为是“空的”,那么最好的选择是引入某种空间树,它可以让您高效地查询您的世界,以查看特定区域中的对象。例如:(正如Eric所建议的)或

按照描述创建此对象,无论是作为标准数组还是锯齿数组,都会破坏允许CPU运行的引用位置。我建议您使用如下结构:

class BigArray 
{
    ArrayCell[,,] arrayCell = new ArrayCell[32,16,32];

    public int this[int i, int j, int k]
    { 
        get { return (arrayCell[i/64, j/64, k/64])[i%64, j%64, k%16]; } 
    }
}


class ArrayCell 
{
    int[,,] cell = new int[64,64,64];

    public int this[int i, int j, int k] 
    { 
        get { return cell[i,j,k]; } 
    }  
}

非常感谢所有试图帮助我理解和解决问题的员工

我尝试了几种能够加载大量数据并存储在表中的解决方案。 两天后,这里是我的测试,最后是解决方案,它可以将4'191'893'824
条目存储到一个数组中

我添加了我的最终解决方案,希望有人能提供帮助

目标 我记得目标是:初始化一个整数数组[2048/1024/2048],用于存储4'191'893'824数据


测试1:使用JaggedArray方法(失败)
引发系统内存不足异常

            /* ******************** */
            /* Jagged Array method  */
            /* ******************** */
            
            // allocate the first dimension;
            bigData = new int[2048][][];
            for (int x = 0; x < 2048; x++)
            {
                // allocate the second dimension;
                bigData[x] = new int[1024][];
                for (int y = 0; y < 1024; y++)
                {
                    // the last dimension allocation
                    bigData[x][y] = new int[2048];
                }
            }
/*******************/
/*锯齿阵列法*/
/* ******************** */
//分配第一维度;
bigData=newint[2048][];
对于(int x=0;x<2048;x++)
{
//分配第二维度;
bigData[x]=newint[1024][];
对于(int y=0;y<1024;y++)
{
//最后一个维度分配
bigData[x][y]=新整数[2048];
}
}

测试2:采用列表法(失败)
引发系统内存不足异常(将大数组分成几个小数组..不起作用,因为“列表”允许最大“2GB”Ram分配,就像简单数组一样。)

/*******************/
/*列表法*/
/* ******************** */
List bigData=新列表(512);
对于(int a=0;a<512;a++)
{
Add(newint[256,128,256]);
}

测试3:带有MemoryMappedFile(解决方案)
我终于找到了解决办法! 使用包含虚拟内存中文件内容的类“内存映射文件”

与我在codeproject上找到的自定义类一起使用。初始化很长,但效果很好

        /* ************************ */
        /* MemoryMappedFile method  */
        /* ************************ */

        string path = AppDomain.CurrentDomain.BaseDirectory;            
        var myList = new GenericMemoryMappedArray<int>(2048L*1024L*2048L, path); 
        using (myList)
        {
            myList.AutoGrow = false;

            /*
            for (int a = 0; a < (2048L * 1024L * 2048L); a++)
            {
                myList[a] = a;
            }
            */

            myList[12456] = 8;
            myList[1939848234] = 1;
            // etc...
        }
     
/*************************/
/*记忆表象法*/
/* ************************ */
字符串路径=AppDomain.CurrentDomain.BaseDirectory;
var myList=新的GenericMemoryMappedArray(2048L*1024L*2048L,路径);
        /* ************************ */
        /* MemoryMappedFile method  */
        /* ************************ */

        string path = AppDomain.CurrentDomain.BaseDirectory;            
        var myList = new GenericMemoryMappedArray<int>(2048L*1024L*2048L, path); 
        using (myList)
        {
            myList.AutoGrow = false;

            /*
            for (int a = 0; a < (2048L * 1024L * 2048L); a++)
            {
                myList[a] = a;
            }
            */

            myList[12456] = 8;
            myList[1939848234] = 1;
            // etc...
        }