0

在我的第一个应用程序原型中,我必须从硬盘顺序读取大约 400,000 个文件(每个 4KB 文件,总共大约 1.5 GB 数据),并对从每个文件读取的数据进行一些操作,并将结果存储在 RAM 中。通过这种机制,我是先访问一个文件的I/O,然后再利用CPU进行操作,然后继续访问另一个文件,但过程非常缓慢。

为了解决这个问题,现在我们首先读取所有文件,并将所有文件数据存储在 RAM 中,然后进行操作(利用 CPU)。它带来了显着的改善。

但是在我的第二个开发阶段,我必须读取 20 GB 的数据,现在我无法将这些数据存储在 RAM 中。并且,具有 CPU 利用率的单次读取操作是非常耗时的操作。

有人可以建议一些方法来解决这个问题吗?

我正在使用 C 语言在 Windows 上使用 Visual Studio 编译器开发此应用程序。

4

3 回答 3

4

There's a technique called Asynchronous I/O (AIO) that lets you keep doing some processing with the CPU while a file is read in the background. You can use this to read the next few files at the same time as you're processing a file.

The various AIO calls are OS-specific. On Windows, Microsoft call it "Overlapped I/O". See this Wikipedia page or this MSDN page for more info.

于 2012-12-17T18:58:26.567 回答
1

为了解决这个问题,现在我们首先读取所有文件,并将所有文件数据存储在 RAM 中,然后进行操作(利用 CPU)。

(假设文件可以独立处理......)

你已经成功了一半。与其等到所有文件都加载到 RAM 中,不如在加载任何文件后立即开始处理。那将是一种流水线形式。

您将需要三个组件:

  1. 读取文件的线程1 (“生产者”)。
  2. 处理文件的线程2 (“消费者”)。
  3. 它们之间有一个消息队列3

生产者以您已经在执行的方式读取文件,但不是处理它们,而是将它们排入消息队列。消费者线程一直等待,直到它可以将文件从队列中出列,处理它,然后立即释放已被文件占用的内存并继续等待队列。

如果您可以通过从头到尾顺序遍历文件来处理文件,您甚至可以设计一个更细粒度的“流式处理”,其中文件将被读取和处理成块,这可以进一步降低峰值内存消耗(例如,如果您有一些不再需要完整保存在内存中的超大文件)。


1或一组线程来并行化 I/O,如果您预计从多个物理磁盘读取。

2或一组线程使 CPU 内核饱和,如果处理文件并不比读取文件便宜。

3你不需要花哨的持久分布式消息队列。只是一个直接的内存队列,.NET 中的 a-la BlockingCollection(我相信你会发现纯 C 的类似内容)。

于 2012-12-18T12:41:38.890 回答
0
  1. 创建将文件读入 RAM 的线程(循环中)。
  2. 在单独的线程中处理 RAM 中的数据,并在处理后释放 RAM。
  3. 在受互斥体保护的共享对象中保留有关文件(读取和处理)的限制和记录轮询。
  4. 将信号量用于资源(RAM 中的文件)生产/使用同步。
于 2012-12-17T21:14:47.223 回答