您所获得的FIR和SMA答案对您而言很不错,但是我想借此机会推动更通用的方法。
您这里拥有的是数据流:无需分三步来构造程序(获取数据,计算,输出结果),而这需要一次将所有数据加载到内存中,而是可以将其构造为管道。
管道从流开始,对其进行转换,然后将其推入接收器。
在您的情况下,管道如下所示:
- 从磁盘读取项目,一次发射一个项目
- 一次接收一个项目,对于接收到的每个项目,发出最后接收的5个(循环缓冲区所在的位置)
- 一次接收项目5,每个组计算结果
- 接收结果,将其写入磁盘
C ++倾向于使用迭代器而不是流,但是说实话,流更易于建模(有一个建议范围类似于流):
template <typename T>
class Stream {
public:
virtual boost::optional<T> next() = 0;
virtual ~Stream() {}
};
class ReaderStream: public Stream<Item> {
public:
boost::optional<Item> next() override final;
private:
std::ifstream file;
};
class WindowStream: public Stream<Window> {
public:
boost::optional<Window> next() override final;
private:
Window window;
Stream<Item>& items;
};
class ResultStream: public Stream<Result> {
public:
boost::optional<Result> next() override final;
private:
Stream<Window>& windows;
};
然后,管道如下所示:
ReaderStream itemStream("input.txt");
WindowStream windowStream(itemsStream, 5);
ResultStream resultStream(windowStream);
std::ofstream results("output.txt", std::ios::binary);
while (boost::optional<Result> result = resultStream.next()) {
results << *result << "\n";
}
流并不总是适用的(当您需要随机访问数据时它们将不起作用),但是当它们出现时,它们会摇摆:通过对非常少量的内存进行操作,您可以将其全部保留在CPU缓存中。
另外请注意:您的问题似乎是“令人尴尬的并行”,您可能希望将大文件拆分为多个块(请注意,对于5个窗口进行处理,每个边界需要4个公共元素)然后并行处理这些块。
如果CPU是瓶颈(而不是I / O),则可以通过在将文件以大致相等的数量分割之后为每个内核启动一个进程来加快处理速度。
V
而不是新的数组中。不过,从根本上讲,我认为您的问题要么在算法中,要么在数据结构中,并且由于我们没有任何细节,因此很难知道如何有效地做到这一点。