我的问题是关于提示和技巧。我正在研究项目,我有一个非常大的(~1Gb)文件和数据。首先,我需要提取数据。这种提取需要10分钟。然后我做计算。下一次计算取决于之前的。我们称它们为calculate1,calculate2,依此类推。假设我已经完成了提取部分,我目前面临两个问题:
考虑到第一个问题,我认为,如果数据库比读取文件更快,某种数据库可能会有所帮助,我怀疑。
如果我将大程序拆分为较小的程序,可能会克服第二个问题,每个程序都会执行:读取文件 - 写东西 - 写入文件。所以下一阶段总是可以读取之前的文件,用于调试。但它为文件I / O引入了许多浪费的代码。
我认为这两个问题都可以通过一些策略来解决,例如:write和test extract模块,而不是启动它,让它将所有数据提取到RAM中。比写计算1,并以某种方式从提取模块的RAM中直接直接获取数据。等等每一次计算都是如此。所以我的问题是:
顺便说一下,我在Perl上编写这个任务是因为我需要它很快,但我稍后会在C ++或C#上重写它,所以任何语言特定或语言无关的答案都欢迎。
谢谢!
[编辑]
数据文件不会改变它就像大不可变的知识源。它不是1Gb,它不需要10分钟阅读它。我只想说,那个文件很大,阅读时间很长。在我的机器上1 Gb读取+解析文件到正确的对象大约需要一分钟。这仍然很糟糕。
[/编辑]
答案 0 :(得分:1)
在我当前的系统上,Perl会在2秒内将整个1GB文件复制到内存中。所以我相信你的问题不是读取文件而是解析它。
因此,我能想到的直接解决方案是预先解析它,例如,将您的数据转换为实际的代码源。我的意思是,您可以直接在脚本中准备数据并对其进行硬编码(当然使用其他文件)。
但是,如果读取是一个实际问题(我怀疑),您可以使用将数据存储在内存中的数据库(example)。无论如何,它会更快,因为您的数据库在启动时会读取一次数据,并且您不会像程序那样频繁地重新启动数据库。
答案 1 :(得分:1)
解决此类问题的想法如下:
参加3个课程:
并使用共享内存在它们之间交换数据。
对于那个大文件,我猜你有一个对象类型的大量数据,可以存储在共享内存中的循环缓冲区中(我建议使用boost :: interprocess)。
Reader将持续读取输入文件中的数据并将其存储在共享内存中。 与此同时,一旦有足够的数据读取进行计算,分析器将开始处理它并将结果存储到另一个循环缓冲区共享内存文件中。 一旦在第二个共享内存中进行了一些计算,Writer就会读取它们并将它们存储到最终的输出文件中。
您需要确保所有进程都正确同步,以便他们能够同时完成工作并且您不会丢失数据(数据在处理之前不会被覆盖或保存到最终文件中)。
答案 2 :(得分:1)
我喜欢doqtor给出的答案,但是为了防止数据被覆盖,一个好的帮助器类来启用和禁用线程中的关键代码段就可以了。
{{1}}
如果你在使用共享内存的关键部分的范围内,这样的类将允许你阻塞特定的线程 另一个线程目前可以访问它。这将导致此线程 代码被锁定,直到当前线程完成其工作和此 课程超出了范围。
在另一个类中使用这个类非常简单:在你的类中 想要在其.cpp文件中阻塞一个线程,你需要创建一个这种类型的静态变量,并调用API的函数来初始化它。然后 你可以使用BlockThread类来锁定这个线程。
SomeClass.cpp
{{1}}
这就是关于它,一旦这个对象超出了静态成员的范围 在对象析构函数中以及此对象熄灭时清除 范围也是如此,BlockThread类及其Destructor在那里清理它。 现在可以使用这个共享内存。如果您遍历容器以在此数据为共享类型时添加,插入或查找和访问元素,则通常需要使用此类。
对于在同一数据集的内存中运行的3个不同线程,一个好的概念是拥有3个或4个缓冲区,每个缓冲区大小约为4MB,并使它们按旋转顺序工作。 Buff1获取数据然后Buff2获取数据,而Buff2获取数据Buff1正在解析数据或传递它以存储用于计算,然后Buff1等待直到Buff3或4完成,等待你有多少缓冲区。然后这个过程再次开始。这与Sound Buffers在读取声音文件以进行音频流或将三批三角形发送到图形卡时使用的原理相同。换句话说,它是批处理类型的过程。