C# 扩展使用数组以防止内存不足异常的简单方法是什么?
但我到目前为止的经验是,当我定义大于100的新数组时,它将从内存中消失 我的想法是,初始化四个大小为100的新数组。并使用四个新阵列,从不同的初始计数器开始,如下所示:C# 扩展使用数组以防止内存不足异常的简单方法是什么?,c#,arrays,out-of-memory,C#,Arrays,Out Of Memory,但我到目前为止的经验是,当我定义大于100的新数组时,它将从内存中消失 我的想法是,初始化四个大小为100的新数组。并使用四个新阵列,从不同的初始计数器开始,如下所示: tempData[30][40, 400, 400, 5] float[][,]tempData0=新的float[30][,]; 浮点[][,]tempData1=新浮点[30][,]; 浮点[][,]tempData2=新浮点[30][,]; 浮点[][,]tempData3=新浮点[30][,]; 私有void Init
tempData[30][40, 400, 400, 5]
float[][,]tempData0=新的float[30][,];
浮点[][,]tempData1=新浮点[30][,];
浮点[][,]tempData2=新浮点[30][,];
浮点[][,]tempData3=新浮点[30][,];
私有void InitTempData()
{
const int FocusSize=100;
尝试
{
对于(int i=0;i<30;i++)
{
tempData0[i]=新浮点[40,聚焦,聚焦,5];
tempData1[i]=新浮点[40,聚焦,聚焦,5];
tempData2[i]=新浮点[40,聚焦,聚焦,5];
tempData3[i]=新浮点[40,聚焦,聚焦,5];
}
}
捕获(OutOfMemoryException ex)
{
MessageBox.Show(例如Message);
}
}
//使用不同初始计数器的tempData0、tempData1、tempData2和tempData3
对于(int i=0;i<30;i++)
{
对于(int x=0;x
我的上述想法是正确的做法吗?或者是否有其他扩展数组使用的选项 这是一个相当大的数组:
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
}
}
}
假设您有那么多的空闲内存,并且正在运行64位进程(大于2/3GB需要),那么您可能遇到了麻烦,因为阵列在内存中是作为连续块布置的
在上面使用[30][40400400,5]的示例中,您要求CLR查找30个128Mb内存块
见:
您可以尝试创建引用较小数组的列表,或者简单地将其声明为“锯齿”数组,以避免连续内存问题(代价是取消对数组数组的引用时性能最差)
i、 浮点数[30][40][400][400][5]它必须是数组吗 我将创建一个带有getter和setter的类。然后,内部存储器可以使用更小的阵列
30 * 40 * 400 * 400 * 5 * (4 bytes) ~= 3.6GB total
公共类五维数据{
private const int BucketSize=16384;//将对象排除在LOH之外
私人T[][]\U桶;
私有整数x,y,z,v;
公共五维数据(整数x,整数y,整数z,整数u,整数v){
if(x<0)
抛出新ArgumentOutOfRangeException(“x”);
if(y<0)
抛出新ArgumentOutOfRangeException(“y”);
if(z<0)
抛出新ArgumentOutOfRangeException(“z”);
if(u<0)
抛出新ArgumentOutOfRangeException(“u”);
if(v<0)
抛出新ArgumentOutOfRangeException(“v”);
_x=x;
_y=y;
_z=z;
_u=u;
_v=v;
长总尺寸=((长)x)*y*z*u*v;
整数totalbucket=(整数)(totalSize/BucketSize)+1;
_bucket=新的T[totalbucket][];
对于(int ii=0;iix)
抛出新ArgumentOutOfRangeException(“x”);
如果(y<0 | | y>|y)
抛出新ArgumentOutOfRangeException(“y”);
如果(z<0 | | z>z)
抛出新ArgumentOutOfRangeException(“z”);
如果(u<0 | | u>_)
抛出新ArgumentOutOfRangeException(“u”);
如果(v<0 | | v>|v)
抛出新ArgumentOutOfRangeException(“v”);
长索引=(长)x*_y*_z*_*_v+
(长)y*_z*_*_v+
(长)z*\u*\u v+
(长)u*\u v+
(长)v;
收益指数;
}
}
如果您使用的是Windows 32位(86x),则在添加新元素之前,必须检查内存大小
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;
}
}
获取当前进程并使用:Process proc=Process.GetCurrentProcess(); 私有存储器程序64
如果我没有弄错的话,您声明这些数组的方式将使您得到锯齿状数组的数组。如果您确定这正是您想要做的,也许您应该尝试使用x64目标构建?它在.net4.0上运行。我刚刚发现,如果我在.net4.5上这样做,它可以使用config-like设置为true。每个多维数组(即
float[40400400,5]
)需要128 MB的连续内存。总而言之,您为100个阵列分配的内存略多于12.8GB。您的计算机上有那么多可用内存吗?您可以增加分页文件的大小,这可能允许您分配内存。但是你的表现会受到影响。您必须找到一些方法来减少内存需求或获得更多RAM。没有“魔法”能让你把12.8GB的东西放进8GB的袋子里。我能知道吗
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;
}
}
// 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
}