【问题标题】:Perl : Reading and processing multiple files in parallelPerl:并行读取和处理多个文件
【发布时间】:2015-01-14 22:47:09
【问题描述】:

我有一个需要在 Perl 中阅读的文件(我们称它为 registered_students.txt)。该文件每行都有数据,因此需要参考其他文件以获取更多信息。

例如,主数据库将具有名称和地址。但是根据每个人的国籍,我必须参考其他文件(按国家排序)才能找到匹配的姓名、国籍和家庭住址。

假设我有 100 个 name_of_country.txt 文件,并且我的 registered_students.txt 中有 10,000 行。我的问题是:

  • 我是否阅读了 registered_students.txt 中的每一行并逐个解析其他 100 个文件以找到匹配项?这似乎是一种处理这些数据的糟糕方式。有没有更快的方法来做到这一点?
  • 我可以在并行模式(多线程)下执行这个过程吗?

谢谢, 汉斯

【问题讨论】:

  • “这似乎是一种处理这些数据的糟糕方式。” 是的。 “有更快的方法吗?” 使用数据库而不是纯文本文件。
  • 原始数据仅以txt文件的形式提供,要求仅使用perl。
  • 看看DBD::SQLite。它是独立的(您不必安装单独的数据库服务器),并且可能比您自己破解的任何东西都要快得多。当然,您必须先将初始数据集加载到数据库中……这些文本文件是否经常更改?
  • 如果您的文件是 CSV 格式,您可以使用 DBD::CSV。否则,按照其他人的建议,在处理之前执行相同的操作并将文件导入 SQLite 表,或者至少导入 CSV 文件。
  • 显示来自不同文件的一些示例行;你在问什么并不完全清楚。另外,您谈到阅读文件;你想用这些信息做什么?如果输出到文件,也显示一个示例

标签: multithreading perl


【解决方案1】:

您在此处尝试执行的操作类似于将两个表中的数据连接在一起时数据库引擎必须执行的操作。数据库引擎通常有许多不同的连接计划可供选择,它会尝试根据对每个表中数据的了解来选择最佳的连接计划。

这同样适用于您。有几种方法可以连接数据,最好的方法取决于每个输入文件的大小、是否预先排序等因素。

一些可能的方法:

  1. 一个“嵌套循环”,您可以在其中读取 registered_students.txt 文件的每一行,并为每一行遍历其他文件以查找匹配项。不太可能很快,如果文件太大而无法使用任何其他解决方案,您可能只会选择此选项。

  2. “哈希连接”,您可以将一半要连接的数据(在您的示例中,可能是 name_of_country.txt)读取到由哈希索引的数据结构中。然后对于其他文件的每一行,您可以在哈希中查找相应的行。这可以是相当高的性能,只要有足够的内存来一次存储两组数据中的至少一组。

  3. 如果两个文件都按某种排序顺序,根据相同的键排序,您也许可以使用“合并连接”。在这里您可以一次从两个文件中读取行,将记录匹配在一起,就像拉链中的牙齿一样。

上面假设了一个简单的情况,其中有两个必须连接的数据文件。您的问题涉及 100 个不同的 name_of_country.txt 文件,这可能会使事情复杂化。

关于您的第二个问题-您可以使用并行处理吗-这可能仅在处理受 CPU 限制时才有用。除非您发现它实际上受 CPU 限制,否则可能无法保证生成分叉或线程解决方案的复杂性。

最后 - 如果您要对同一数据进行多次分析运行,建议将数据导入真实数据库并使用该运行查询。这将为您节省大量的编码工作。

【讨论】:

    【解决方案2】:

    我会将您的问题视为:如何有效地执行两个文件的“加入”操作,这就是答案。

    实际上在 Unix 中有一个join 命令。 http://linux.die.net/man/1/join

    假设你有两个文件,student 和 student_with_country:

    student: [name] [age] [...]
    student_with_country: [name] [country] [...]
    

    你可以这样做:

    join student student_with_country (by default, it will join based on the first field)
    

    那么问题是如何通过使用多核来使其更快?

    答案是parallel 命令。基本上,您可以使用它运行一个简单的 map-reduce 程序。例如,在这种情况下

    cat student_with_country | parallel --block 10M --pipe join student - 
    

    它将student_with_country文件分成10M块并并行运行join命令。这样,您就可以利用多核的力量。

    【讨论】:

    • 感谢您的建议。如果您只有两个文件并且它们具有相同的行数,这可能会最有效。问题是文件 student_with_country 与学生文件的格式不同,并且还有我不需要的额外垃圾。
    • join 假定文件已排序。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多