Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何直接有效地访问非常大的文本文件?_C++_C_File Io_Mpi - Fatal编程技术网

C++ 如何直接有效地访问非常大的文本文件?

C++ 如何直接有效地访问非常大的文本文件?,c++,c,file-io,mpi,C++,C,File Io,Mpi,我有一个非常大的文本文件(+10GB),我想读一些数据挖掘技术。 为此,我将并行技术与MPI结合使用,因此许多进程可以一起访问同一个文件。 事实上,我希望每个进程读取N行。由于文件不是结构化的(相同数量的字段,但每个字段可以包含不同数量的字符),我有义务解析文件,这不是并行的,而且需要很多时间。 是否有任何方法可以直接访问特定数量的行,而无需对行进行计数和分析? 感谢您的帮助。如果您的文件没有其他索引,则没有直接的方法 为它编制索引可能是值得的(扫描一次以找到所有的行尾,并存储每行或每段行的偏移

我有一个非常大的文本文件(+10GB),我想读一些数据挖掘技术。 为此,我将并行技术与MPI结合使用,因此许多进程可以一起访问同一个文件。
事实上,我希望每个进程读取N行。由于文件不是结构化的(相同数量的字段,但每个字段可以包含不同数量的字符),我有义务解析文件,这不是并行的,而且需要很多时间。 是否有任何方法可以直接访问特定数量的行,而无需对行进行计数和分析?
感谢您的帮助。

如果您的文件没有其他索引,则没有直接的方法

为它编制索引可能是值得的(扫描一次以找到所有的行尾,并存储每行或每段行的偏移量)。如果您需要多次处理该文件,并且该文件没有更改,则索引的成本可以通过在后续运行中轻松使用索引来抵消

否则,如果您不需要所有作业都具有完全相同的行数/项数,您可以将其捏造出来。
寻找一个给定的偏移量(比如1G),并寻找最近的线分隔符。在偏移量2G等处重复,直到找到足够的断点


然后,您可以在已识别的每个块上启动并行任务。

没有:除非您不读取未知数据,否则没有人会知道有多少新行字符。这个问题的复杂性是O(n),因此意味着至少要读取一次整个文件。然后,您可能希望构建一个索引表,在其中记录文件中有新行字符的位置:这可供所有进程使用,通过fseek,您可以大大加快进一步的访问速度。

除了此处提到的选项之外,还有一些不需要扫描整个文件的选项:

  • 创建一个主进程,通过管道/FIFO将行推送到执行实际处理的子进程。这可能会稍微慢一点,但如果说子流程中90%的时间是实际的文本处理,那么应该可以

  • 一个愚蠢但有效的把戏:假设你有N个进程,你可以通过argv或其他东西来判断每个进程是“序列号”,例如
    处理器-序列号[1 | 2 | 3…N]-num|procs N
    ,它们都可以读取相同的数据,但只处理那些有
    lineno%num|procs==serial|number
    的行。效率有点低,因为它们都会读取整个数据,但同样,如果它们只在每N行上工作,而这正是消耗大部分时间的原因,那么应该可以


  • 感谢您的回复,这似乎是一个很好的解决方案。我将这样做,看看它是否值得,因为在串行模式下,我读取一个文件,然后每行我做许多CPU计算。到目前为止,我有两种解决方案:我解析文件来构造一个索引文件,然后所有进程都可以使用它。或者我让一个进程从文件中读取,让其他进程进行计算。对于O(n),我引用了这个符号:顺便说一下,索引很容易并行执行。如果有多个进程,也可以将文件拆分为索引,因此假设第一个进程读取第1 Gb、第2 Gb、第2 Gb等,并将新行字符的位置保存到同一共享资源中。这也可以加快索引速度。但是,请不要忘记,根据您使用的存储硬件,顺序读取可能会快得多。因此,这是关于混合两个步骤1-如您所说,让N个进程获取索引。2-对于cpu计算,每个进程直接使用fseek()访问特定偏移量。那看起来不错。谢谢你的回复。我认为第二个想法更好,因为我通常会按时解析文件。考虑到这个解决方案,我将使每个进程从一个特定的偏移量进行访问,比如说(文件大小/进程编号*进程排名),然后我寻找新行的开头。因此,我会在更糟糕的进程行数上松懈?+1扫描一次以找到换行符,并将索引交给其他进程绝对比其他进程更可取,因为任何随机搜索都比并行解析文本文件中每行的某些字段所能获得的代价高出几个数量级。顺序读取和从缓冲区缓存中提取速度很快,其他一切都会破坏每一次优化。
    fseek
    完全盲目地寻找。它将文件指针移动指定的字节数,即全部。这是否是固定时间可能取决于文件系统实现的细节,但考虑到您的场景,这并不重要-搜索将是“瞬时的”)。(除非文件位于机械磁带机上…)请注意,如果解决方案涉及随机寻道,则必须以二进制模式打开文件(并使用与平台相关的行终止符定义)。如果文件是以文本模式打开的,唯一合法的搜索是在前面、末尾或
    tell
    返回的位置。您可以对文件进行内存映射,让OS/FS找出最佳的缓存和搜索方法(假定在OS/FS中进行了优化)。+1用于替代思考。有时候,赢得比赛的最好办法就是改变规则。