高效的文件I / O和字符串转换为浮点数

时间:2010-01-14 19:22:45

标签: performance multithreading file-io large-data-volumes

我有一些巨大的(几千兆字节)ASCII文本文件,我需要逐行读取,将某些列转换为浮点数,并对这些数字执行一些简单的操作。这是非常简单的东西,除了我认为必须有一种方法来加快它的速度。该程序从不使用相当于100%的CPU内核,因为它花了很多时间等待I / O.与此同时,它花费了足够的时间进行计算而不是I / O,只需要8-10 MB /秒的原始磁盘I / O.我见过我的硬盘好多了。

它可能有助于在单独的线程中进行I / O和处理吗?如果是这样,实现这个的有效方法是什么?一个重要的问题是如何处理内存分配以保持每一行,这样我就不会遇到瓶颈。

编辑:我现在正在使用D编程语言,版本2标准库,主要是更高级别的功能。 std.stdio.File使用的缓冲区大小为16 KB。

4 个答案:

答案 0 :(得分:1)

如果你没有达到100%的CPU,那么你就受到了I / O限制,并且多线程不会看到太多/任何改进 - 你只需要几个线程等待I / O.实际上,如果他们访问文件的不同部分,你可能会引入磁盘寻找并使事情变得更糟。

首先看一下简单的事情:你能增加I / O可用的缓冲RAM量吗? (例如在C ++中,FILE对象的标准I / O缓冲区很小(例如4kB),设置较大的缓冲区(例如64kB)会对吞吐量产生巨大影响)。

您可以在I / O请求中使用更大的缓冲区大小:例如将64KB原始数据读入一个大缓冲区,然后自己处理,而不是一次读取一行或一个字节。

您在输出任何数据吗?通过在RAM中缓存它而不是立即将其写回磁盘,您可以将IO限制为纯粹读取输入文件,并帮助提高速度。

你可能会发现,一旦你加载了大量的数据缓冲区,你开始变成了CPU绑定,那么你可以考虑多线程 - 一个线程来读取数据,另一个线程来处理它。

答案 1 :(得分:0)

如果你有足够的内存,你可以把整个文件读成一个字符串,在行分隔符上标记它,然后处理你想要的标记。

在java中,您将使用StringBuilder对象将文件内容读入其中。您还希望使用以下内容启动具有足够内存限制(在此示例中为2GB)的jvm:

java -Xmx 2048 -Xms 2048 -jar MyMemoryHungryApp.jar

如果您不想将整个文件读入字符串,您可以批量迭代地读取它并处理批次。

实际上,根据文件格式的细节,你可以使用CSVReader一个开源Java包(project page)来读取你的文件到readAll()方法的内存,你就会结束用List<String[]>来你可以去镇上。)。

答案 2 :(得分:0)

首先,我会接受你所拥有的程序,并获得它的叠印。这将确定I / O花费了多少时间,以及CPU的耗费量。

然后,如果I / O占主导地位,我会确保我正在读取尽可能大的缓冲区,以尽量减少磁头运动。

然后,如果我看到I / O在CPU上等待,然后CPU等待I / O,我会尝试进行异步I / O,这样一个缓冲区就可以加载而CPU在另一个上运行。 (或者你可以用读者线程来读取备用缓冲区。)

如果I / O不占优势并且CPU占主导地位,那么我会看到什么叠加告诉我有关CPU活动的信息。如果在浮点数的去格式化中花费了过多的时间,并且如果数字格式相当简单,我会考虑自己解析它们,因为我可以利用更简单的格式。

这有帮助吗?

答案 3 :(得分:0)

通常情况下,操作系统会尝试提前读取,如果您不受CPU限制,则应该接近硬盘限制速度。

原因可能是:

  • 大文件碎片化(您可能会对卷进行碎片整理并检查其是否更好)
  • 操作系统不使用预读(作为解决方案:在Windows下,您可以使用带有将要扫描文件的标志的CreateFile)
  • 你没有使用有效的缓冲(例如,如果你从一个OS文件中读取一次只有几个字节的东西会很慢。(你可能会尝试一次读取更大的块)。

当你受CPU限制时,你应该开始考虑更有效的数据解析。