【问题标题】:How to Parallelize a Python program on Linux如何在 Linux 上并行化 Python 程序
【发布时间】:2019-06-27 18:49:59
【问题描述】:

我有一个脚本,它接受input a list of filenames 并循环它们以为每个输入文件生成一个输出文件,所以我认为这种情况可以很容易地并行化。

我有一台 8 核机器。

我尝试在此命令上使用-parallel 标志:

python perfile_code.py list_of_files.txt

但我无法使其工作,即具体问题是:如何在 bash 中使用并行与 Linux 中的 python 命令,以及上述特定情况的参数。

有一个 Linux 并行命令 (sudo apt-get install parallel),我在某处读到它可以完成这项工作,但我不知道如何使用它。

大部分互联网资源都在 python 中解释了如何做到这一点,但它可以在 bash 中完成吗?

请帮忙,谢谢。

Based on an answer, here is a working example that is still not working, please suggest how to make it work.

我有一个包含 2 个文件的文件夹,我只想在此示例中并行创建具有不同名称的副本。

# filelist is the directory containing two file names, a.txt and b.txt.
# a.txt is the first file, b.xt is the second file
# i pass an .txt file with both the names to the main program

from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path
import sys

def translate(filename):
    print(filename)
    f = open(filename, "r")
    g = open(filename + ".x", , "w")
    for line in f:
        g.write(line)

def main(path_to_file_with_list):
    futures = []
    with ProcessPoolExecutor(max_workers=8) as executor:
        for filename in Path(path_to_file_with_list).open():
            executor.submit(translate, "filelist/" + filename)
        for future in as_completed(futures):
            future.result()

if __name__ == "__main__":
     main(sys.argv[1])

【问题讨论】:

  • 为什么要投票赞成关闭?这是一个非常具体的问题,询问如何在 bash 和 python 中使用并行以及参数。我已编辑问题以使其更清楚,请重新考虑。
  • 您对并行性主题缺乏基本的了解。 -parallel 不是 Python 的有效命令行选项。并行操作的编程通常需要程序员主动开发策略。我建议在谷歌上搜索“python 并行”。
  • @Ouroborus 不,不考虑这个opensource.com/article/18/5/gnu-parallel 我想与这个并行运行一个python程序..对于一个非常特殊的情况..如果一个任意转换程序可以通过管道传输到并行..为什么不使用 python 程序?
  • 这仍然需要您了解并行性的一般工作原理以及您的软件能够在该环境中运行。正如您所描述的,您当前的 python 脚本不会从 gnu parallel 中受益。阅读和理解您链接的文章将大大有助于您了解您需要做什么。
  • 没有交钥匙--parallel 标志。您需要自己编写并行性,请参阅:multiprocessing

标签: python linux python-3.x python-2.7 parallel-processing


【解决方案1】:

根据您的评论,

@Ouroborus 不,不考虑这个 opensource.com/article/18/5/gnu-parallel 我想与这个并行运行一个 python 程序..对于一个非常具体的情况..如果可以是任意转换程序管道到并行..为什么不使用 python 程序?

我认为这可能会有所帮助:

convert 不是随便选择的。之所以选择它,是因为它是一个广为人知的程序,它(大致)将通过命令行提供的单个输入文件映射到也通过命令行提供的单个输出文件。

典型的 shell for 循环可用于迭代列表。在您链接的文章中,他们展示了一个示例

for i in *jpeg; do convert $i $i.png ; done

这(再次,粗略地)获取文件名列表并将它们逐个应用于命令模板,然后运行该命令。

这里的问题是for 必须等到一个命令完成后再运行下一个命令,因此可能未充分利用当今的多核处理器。

parallelfor 的一种替代品。它假设一个命令可以同时执行多次,每次都有不同的参数,而每个实例都不会干扰其他实例。

在文章中,他们展示了一个使用parallel的命令

find . -name "*jpeg" | parallel -I% --max-args 1 convert % %.png

这相当于前面的for 命令。区别(仍然大致)是parallel 同时运行模板化命令的多个变体,而不必等待每个变体完成。


针对您的具体情况,为了能够使用parallel,您需要:

  • 调整您的 python 脚本,使其接受一个输入(例如文件名)和一个输出(也可能是文件名),两者都通过命令行。
  • 弄清楚如何设置 parallel 以便它可以接收这些文件名的列表,以便插入到命令模板中,从而分别在每个文件上运行您的 python 脚本。

【讨论】:

  • 你能看看我在上面的问题中编辑的工作示例吗?
  • @Rafael 除了明显的语法错误之外,它看起来应该符合您的预期。初步测试表明它有效。
【解决方案2】:

您可以只使用普通的shell for 命令,并将& 背景指示器附加到for 内的python 命令:

for file in `cat list_of_files.txt`;
   do python perfile_code.py $file &
done

当然,假设你的 python 代码会自己生成单独的输出。

就是这么简单。 虽然不常见 - 通常人们会喜欢使用 Python 本身来控制循环的并行执行,如果你可以编辑程序的话。一种不错的方法是在 Python 中使用 concurrent.futures 创建一个包含 8 个工作人员的工作程序池 - 上面的 shell 方法将一次并行启动所有实例。

假设您的代码有一个接受文件名的translate 函数,您的 Python 代码可以写成:

from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path:

def translate(filename):
    ...

def main(path_to_file_with_list):
    futures = []
    with ProcessPoolExecutor(max_workers=8) as executor:
        for filename in Path(path_to_file_with_list).open():
            executor.submit(translate, filename)
        for future in as_completed(futures):
            future.result()

if __name__ == "__main__":
     import sys
     main(argv[1])

这将不依赖于特殊的 shell 语法,并且会处理极端情况和 number-or-workers 处理,而这在 bash 中可能很难正确完成。

【讨论】:

  • 感谢您的工作示例!我试过你的例子,请看一下编辑过的问题,它仍然不起作用。
  • 你写的例子在 python 3 和 2 中都有效吗?
  • 唯一的 Python3.5+ 部分是pathlib.Path。在 Python 2.7 中,只需使用普通的旧 open(path_to_file_wiith_list),而不需要 from pathlib import Pathconcurrent.futures 在 Python 2.7 和更新版本中的工作方式相同。
  • 这可能会使您的机器过载。如果list_of_files.txt 包含 1000000 个名称,那么您的机器很可能会慢到爬行。
  • Python 版本创建了一个工作池。排队的未来对象使用极少量的资源——即使是 1_000_000 个名称在具有 4GB 主内存的机器中也只是小菜一碟。当然,40_000_000 将开始成为某种东西——如果一个文件列表这么大,那么也只需注意创建期货——这将是上面多出 6 或 7 个 LoC 的问题。 shell 版本是的,立即并行启动所有进程 - 即使是几千个文件名也会让任何机器不堪重负。
【解决方案3】:

从您的问题中不清楚您如何串行运行任务。但如果我们假设你运行:

python perfile_code.py file1
python perfile_code.py file2
python perfile_code.py file3
:
python perfile_code.py fileN

那么并行化的简单方法是:

parallel python perfile_code.py ::: file*

如果您有一个每个文件一行的文件列表,请使用:

parallel python perfile_code.py :::: filelist.txt

它将在每个 cpu 线程中并行运行一个作业。因此,如果filelist.txt 包含 1000000 个名称,那么它不会同时运行它们,而只会在一个完成时开始一个新作业。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-17
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多