处理大型(GB级)文件的快速多次处理(Java)

处理大型文件时,有哪些快速多次处理的选项?

我有一个单一文件(最小1.5 GB,但可能达到10-15 GB),需要被读取多次——大约是数百到数千次。服务器拥有大量的RAM(64+ GB)和充足的处理器(24+)。

文件将是顺序的,只读。文件在磁盘上是加密的(敏感数据)。我在读取过程中还使用MessagePack将它们反序列化为对象。

我无法将文件创建的对象存储在内存中——扩展太大了(1.5 GB的文件在内存中会变成35 GB的对象数组)。文件不能存储为字节数组(受限于Java的数组长度为2^32-1)。

我的初步想法是使用内存映射文件,但这也有其自身的限制。

目的是将文件从磁盘读取到内存中进行处理。

大量数据用于机器学习算法,需要多次读取。在计算每次文件通过时,算法本身会使用大量的堆内存,这是不可避免的,因此需要多次读取文件。


回答:

你遇到的问题是无法像同名系统调用那样使用mmap();系统调用可以映射到2^64,而FileChannel#map()不能可靠地映射超过2^30的数据。

然而,你可以将FileChannel包装到一个类中,并创建多个“映射范围”来覆盖整个文件。

我做过类似的事情,但更复杂:largetext。更复杂是因为我还需要进行解码过程,并且加载的文本必须进入内存,而你只是读取字节。较简单是因为我有一个定义的JDK接口需要实现,而你没有。

然而,你可以使用几乎相同的方法,使用Guava和RangeMap<Long, MappedByteBuffer>

我在上面的项目中实现了CharSequence;我建议你实现一个LargeByteMapping接口,取而代之,你可以从中读取你想要的任何部分;或者,嗯,任何适合你的东西。你主要的问题将是定义这个接口。我怀疑CharSequence所做的不是你想要的。

嗯,我有朝一日可能会尝试一下,largetext是一个非常令人兴奋的项目,这看起来像是同一类的事情;但最终更简单!

甚至可以想象一个LargeByteMapping实现,其中一个工厂会创建这样的映射,只有一小部分在内存中,其余部分写入文件;这样的实现也会使用局部性原则:最近查询的文件部分将保留在内存中以便更快访问。

另见这里


编辑 我觉得这里需要更多的解释… MappedByteBuffer不会消耗堆空间!!

它只会消耗地址空间;它几乎相当于ByteBuffer.allocateDirect(),只是它由文件支持。

这里需要做出一个非常重要的区分;以上所有的文本都假设你在读取字节,而不是字符

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注