【发布时间】:2015-07-18 00:10:41
【问题描述】:
我需要处理大量浮点数,但我在 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;
}
paramN 列表的长度很短(当前为 50 或更低),但数据可以是 10m+。当长度为 50 时,我在 1m 数据点以上达到内存限制 (OutOfMemoryException),当长度为 25 时,我在 2m 数据点以上达到限制。 (如果我的计算是正确的,那就是 200MB,加上名称的大小,加上开销)。我可以使用什么来提高此限制?
编辑:我尝试使用最大内部列表大小为 1 List<List<float>>,这在一定程度上增加了限制,但仍然没有达到我想要的程度。 p>
Edit2:我尝试将 List> 中的块大小减小到 8192,我得到了大约 2.3m 元素的 OOM,任务管理器读取了大约 1.4GB 的进程。看起来我需要减少数据源和存储之间的内存使用量,或者更频繁地触发 GC - 我能够在具有 4GB RAM 的 PC 上的 x64 进程中收集 10m 数据点,IIRC 该进程从未超过 3GB
Edit3:我将我的代码压缩为仅处理数据的部分。 http://pastebin.com/maYckk84
Edit4:我查看了 DotMemory,发现我的数据结构确实占用了我正在测试的设置大约 1GB(50ch * 3 参数 * 2m 事件 = 300,000,000 个浮点元素) .我想我需要在 x86 上限制它,或者在我获取数据时弄清楚如何以这种格式写入磁盘
【问题讨论】:
-
你的问题是......?
-
hitting memory limits就像得到OutOfMemoryException之类的东西?而 200MB 是您期望每个 List 中的每个项目占用多少? -
列表容量调整算法在达到限制时将持有数组的大小加倍。这可以证明是非常低效的。是否可以预测您的任何列表的最终长度,从而在施工中提供容量?如果您的任何列表在没有修改的情况下停留了相当长的时间,您应该考虑使用
.TrimExcess(),但要注意.TrimExcess之后的单个添加会导致容量翻倍。 -
您需要使用一种数据结构,将其数据存储在非纯连续数据中(
List<T>在内部使用数组)。您可能希望创建一个自定义数据结构,在现有数组填满时创建新数组,将它们像链表一样菊花链。 .NetStringBuilder从 .Net 4.0 或 4.5 开始执行此操作,因此您可以查看其源代码作为示例。 -
您的代码示例没有充分说明确切的问题。通常,您可能会在内存不足之前达到
List<T>的大小限制,您可以通过创建数据结构来解决此问题,例如List<List<T>>(即列表列表)。但是在 x86 上,您将始终被严格限制在相对较小的数据量(3GB 是理论上的最大值,但实际上实际限制可以低至 1.2-1.4GB)。如果您想要一个实际的答案,请提供a good, minimal, complete code example 可靠地重现问题。