我需要使用大型浮动列表,但我在x86系统上遇到了内存限制.我不知道最终长度,所以我需要使用可扩展类型.在x64系统上,我可以使用<gcAllowVeryLargeObjects>.
我目前的数据类型:
List<RawData> param1 = new List<RawData>();
List<RawData> param2 = new List<RawData>();
List<RawData> param3 = new List<RawData>();
public class RawData
{
public string name;
public List<float> data;
}
Run Code Online (Sandbox Code Playgroud)
paramN列表的长度很低(目前为50或更低),但数据可以是10m +.当长度为50时,我OutOfMemoryException在1m以上的数据点处达到内存限制(),当长度为25时,我在2m以上的数据点达到极限.(如果我的计算是正确的,那就是200MB,加上名称的大小加上开销).我可以用什么来增加这个限制?
编辑:我尝试使用List<List<float>>最大内部列表大小1 << 17(131072),这有点增加了限制,但仍然没有我想要的.
Edit2:我尝试将List>中的块大小减少到8192,并且我得到了大约2.3m元素的OOM,任务管理器读取了大约1.4GB的进程.看起来我需要减少数据源和存储之间的内存使用,或者更频繁地触发GC - 我能够在具有4GB RAM的PC上的x64进程中收集10m数据点,IIRC进程从未超过3GB
Edit3:我将代码缩减为处理数据的部分.http://pastebin.com/maYckk84
编辑4:我看过DotMemory,发现我的数据结构确实占用了我正在测试的设置~1GB(50ch*3 params*2m events = 300,000,000 float elements).我想我需要在x86上限制它,或者在获取数据时弄清楚如何以这种格式写入磁盘
Alo*_*man 15
首先,在x86系统上,内存限制为2GB,而不是200MB.我认为你的问题比那更棘手.你有积极的LOH(大对象堆)碎片.
CLR对小型和大型对象使用不同的堆.如果对象的大小大于85,000字节,则对象很大.LOH是一个非常暴躁的东西,它并不急于将未使用的内存返回给操作系统,并且它在碎片整理方面非常差.
.Net List是ArrayList数据结构的实现,它将元素存储在数组中,它具有固定的大小; 填充数组时,将创建具有双倍大小的新数组.随着您的数据量不断增长的数组是LOH的"饥饿"情景.
因此,您必须使用量身定制的数据结构来满足您的需求.例如,块的列表,每个块足够小,不会进入LOH.这是小原型:
public class ChunkedList
{
private readonly List<float[]> _chunks = new List<float[]>();
private const int ChunkSize = 8000;
private int _count = 0;
public void Add(float item)
{
int chunk = _count / ChunkSize;
int ind = _count % ChunkSize;
if (ind == 0)
{
_chunks.Add(new float[ChunkSize]);
}
_chunks[chunk][ind] = item;
_count ++;
}
public float this[int index]
{
get
{
if(index <0 || index >= _count) throw new IndexOutOfRangeException();
int chunk = index / ChunkSize;
int ind = index % ChunkSize;
return _chunks[chunk][ind];
}
set
{
if(index <0 || index >= _count) throw new IndexOutOfRangeException();
int chunk = index / ChunkSize;
int ind = index % ChunkSize;
_chunks[chunk][ind] = value;
}
}
//other code you require
}
Run Code Online (Sandbox Code Playgroud)
使用ChunkSize= 8000,每个块只需要32,000个字节,因此它不会进入LOH._chunks只有当收集到大约16,000个块时才会进入LOH,这将超过1.28亿个元素(约500 MB).
UPD我已经对上面的样本进行了一些压力测试.操作系统是x64,解决方案平台是x86.ChunkSize是20000.
第一:
var list = new ChunkedList();
for (int i = 0; ; i++)
{
list.Add(0.1f);
}
Run Code Online (Sandbox Code Playgroud)
引发OutOfMemoryException为〜324,000,000个元素
第二:
public class RawData
{
public string Name;
public ChunkedList Data = new ChunkedList();
}
var list = new List<RawData>();
for (int i = 0;; i++)
{
var raw = new RawData { Name = "Test" + i };
for (int j = 0; j < 20 * 1000 * 1000; j++)
{
raw.Data.Add(0.1f);
}
list.Add(raw);
}
Run Code Online (Sandbox Code Playgroud)
在i = 17,j~12,000,000处引发OutOfMemoryException.成功创建了17个RawData实例,每个数据点2000万个,总共约3.52亿个数据点.
| 归档时间: |
|
| 查看次数: |
1826 次 |
| 最近记录: |