1
float[][, , ,] tempData = new float[30][, , ,];

private void InitTempData()
{
    const int FocusSize = 400;
    try
    {
        for (int i = 0; i < 30; i++)
        {
            tempData[i] = new float[40, FocusSize, FocusSize, 5];
        }
    }
    catch (OutOfMemoryException ex)
    {
        MessageBox.Show(ex.Message);
    }
}

我需要使用数组大小​​如下的 tempData:

tempData[30][40, 400, 400, 5]

但是到目前为止我所经历的,OutOfMemory当我定义大小超过 100 的新数组时,它就会消失。

我想到的想法是,我初始化了四个大小为 100 的新数组。并使用四个新数组以不同的初始计数器开始,如下所示:

float[][, , ,] tempData0 = new float[30][, , ,];
float[][, , ,] tempData1 = new float[30][, , ,];
float[][, , ,] tempData2 = new float[30][, , ,];
float[][, , ,] tempData3 = new float[30][, , ,];

private void InitTempData()
{
    const int FocusSize = 100;
    try
    {
        for (int i = 0; i < 30; i++)
        {
            tempData0[i] = new float[40, FocusSize, FocusSize, 5];
            tempData1[i] = new float[40, FocusSize, FocusSize, 5];
            tempData2[i] = new float[40, FocusSize, FocusSize, 5];
            tempData3[i] = new float[40, FocusSize, FocusSize, 5];
        }
    }
    catch (OutOfMemoryException ex)
    {
        MessageBox.Show(ex.Message);
    }
}

//Use the tempData0, tempData1, tempData2, and tempData3 with different initial counter
for (int i = 0; i < 30; i++)
{
    for (int x = 0; x < FocusSize; x++)
    {
        for (int z = 0; z < FocusSize; z++)
        {
            //Use tempData0 here
        }
    }
}

for (int i = 0; i < 30; i++)
{
    for (int x = FocusSize; x < FocusSize * 2; x++)
    {
        for (int z = FocusSize; z < FocusSize * 2; z++)
        {
            //Use tempData1 here
        }
    }
}

for (int i = 0; i < 30; i++)
{
    for (int x = FocusSize * 2; x < FocusSize * 3; x++)
    {
        for (int z = FocusSize * 2; z < FocusSize * 3; z++)
        {
            //Use tempData2 here
        }
    }
}

我的上述想法是正确的做法吗?或者有没有其他选择来扩展数组的使用?

4

3 回答 3

2

这是一个相当大的数组:

30 * 40 * 400 * 400 * 5 * (4 bytes) ~= 3.6GB total

假设您有那么多可用内存并且正在运行 64 位进程(> 2/3GB 需要),那么您可能会遇到困难,因为数组在内存中被布置为连续的块。

在上面使用 [30][40,400,400,5] 的示例中,您要求 CLR 查找 30 个 128Mb 的内存块。

请参阅:http: //blogs.msdn.com/b/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx

您可以尝试创建引用较小数组的列表,或者简单地将其声明为“锯齿状”数组以避免连续内存问题(以取消引用数组的最差性能为代价)。

即浮动[30][40][400][400][5]

于 2013-08-13T02:01:25.893 回答
0

它必须是一个数组吗?

我会创建一个带有 getter 和 setter 的类。然后内部存储可以使用更小的阵列。

public class FiveDimensionalData<T> {
    private const int BucketSize = 16384; // keep object out of LOH
    private T[][] _buckets;
    private int _x, _y, _z, _u, _v;

    public FiveDimensionalData(int x, int y, int z, int u, int v) {
        if (x < 0)
            throw new ArgumentOutOfRangeException("x");
        if (y < 0)
            throw new ArgumentOutOfRangeException("y");
        if (z < 0)
            throw new ArgumentOutOfRangeException("z");
        if (u < 0)
            throw new ArgumentOutOfRangeException("u");
        if (v < 0)
            throw new ArgumentOutOfRangeException("v");

        _x = x;
        _y = y;
        _z = z;
        _u = u;
        _v = v;

        long totalSize = ((long)x)*y*z*u*v;

        int totalBuckets = (int)(totalSize / BucketSize) + 1;
        _buckets = new T[totalBuckets][];

        for (int ii = 0; ii < totalBuckets; ++ii)
            _buckets[ii] = new T[BucketSize];
    }

    public T Get(int x, int y, int z, int u, int v) {
        long bucketIndex = Index(x, y, z, u, v); 

        int bucket = (int)(bucketIndex / BucketSize);
        int positionInBucket = (int)(bucketIndex % BucketSize);

        return _buckets[bucket][positionInBucket];
    }

    public void Set(int x, int y, int z, int u, int v, T value) {
        long bucketIndex = Index(x, y, z, u, v); 

        int bucket = (int)(bucketIndex / BucketSize);
        int positionInBucket = (int)(bucketIndex % BucketSize);

        _buckets[bucket][positionInBucket] = value;
    }

    private long Index(int x, int y, int z, int u, int v) {
        if (x < 0 || x > _x)
            throw new ArgumentOutOfRangeException("x");
        if (y < 0 || y > _y)
            throw new ArgumentOutOfRangeException("y");
        if (z < 0 || z > _z)
            throw new ArgumentOutOfRangeException("z");
        if (u < 0 || u > _u)
            throw new ArgumentOutOfRangeException("u");
        if (v < 0 || v > _v)
            throw new ArgumentOutOfRangeException("v");

        long index = (long)x * _y * _z * _u * _v + 
                     (long)y * _z * _u * _v +
                     (long)z * _u * _v +
                     (long)u * _v +
                     (long)v;
        return index;
    }
}            
于 2013-08-13T07:28:02.867 回答
0

如果您使用的是 Windows 32 位 (86x),则必须在添加新元素之前检查内存大小。

// Here you have to check that the current used memory in your process; this shall not exceed more than 2 GB;
// If you are using  /LARGEADDRESSAWARE than not exceed 4 GB
If (MemoryHelper.CanAllocateObject())
{
 // here add a new elements
}

获取当前进程并使用:
Process proc = Process.GetCurrentProcess(); proc.PrivateMemorySize64;
http://msdn.microsoft.com/en-us/library/s80a75e5%28VS.80%29.aspx

于 2013-08-13T07:53:33.763 回答