Как распараллелить программу на Python в Linux - PullRequest
0 голосов
/ 04 февраля 2019

У меня есть сценарий, который принимает input a list of filenames и циклически повторяет их, чтобы сгенерировать выходной файл для каждого входного файла, так что это случай, который можно легко распараллелить, я думаю.

У меня 8 ядерmachine.

Я пытался использовать флаг -parallel в этой команде:

python perfile_code.py list_of_files.txt

Но я не могу заставить его работать, то есть конкретный вопрос: как использовать параллель в bash скоманда python в Linux вместе с аргументами для конкретного случая, упомянутого выше.

Существует параллельная команда 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])

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Вы можете просто использовать обычную команду оболочки for и добавить индикатор фона & к команде python внутри for:

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

Конечно.Предполагая, что ваш код Python будет генерировать отдельные выходные данные.

Это просто так просто.Хотя это и не обычно - обычно люди предпочитают использовать сам Python для управления параллельным выполнением цикла, если вы можете редактировать программу.Один хороший способ сделать это - использовать concurrent.futures в Python для создания рабочего пула с 8 рабочими - описанный выше подход оболочки запускает все экземпляры параллельно одновременно.

Предполагая, что ваш код имеет функцию 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])

Это не будет зависеть от специального синтаксиса оболочки, и учитывает угловые случаи и обработку числа или рабочих, которые могутТрудно сделать правильно из Баш.

0 голосов
/ 07 февраля 2019

Из вашего вопроса неясно, как вы выполняете свои задачи в последовательном режиме.Но если мы предположим, что вы выполняете:

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

Параллельно будет выполняться одно задание на каждый поток процессора.Поэтому, если filelist.txt содержит 1000000 имен, он не будет запускать их все одновременно, а только начнет новую работу после ее завершения.

0 голосов
/ 04 февраля 2019

Исходя из вашего комментария,

@ Уроборус нет, не рассматривайте это opensource.com/article/18/5/gnu-parallel. Я хочу запустить программу Python вместе с этой параллелью ..для очень конкретного случая ... если произвольная программа конвертирования может быть передана в параллель ... почему бы не программа на Python?

Я думаю, что это может помочь:

convert не был выбран произвольно.Она была выбрана потому, что это более известная программа, которая (приблизительно) отображает один входной файл, предоставленный через командную строку, в один выходной файл, также предоставленный через командную строку.

Типичная оболочка for цикл может быть использован для перебора списка.В статье, на которую вы ссылаетесь, они показывают пример

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

. Это (опять же, приблизительно) берет список имен файлов и применяет их, один за другим, к шаблону команды, а затем запускает эту команду.

Проблема здесь в том, что for обязательно будет ждать завершения команды, прежде чем запускать следующую, и, следовательно, может недостаточно использовать современные многоядерные процессоры.

parallel действует своего родазамены на for.Предполагается, что команда может быть выполнена несколько раз одновременно, каждый с разными аргументами, без вмешательства каждого экземпляра в другие.

В статье они показывают команду, используя parallel

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

, что эквивалентно предыдущей команде for.Разница (все еще приблизительно) в том, что parallel запускает несколько вариантов шаблонной команды одновременно, не обязательно ожидая завершения каждой из них.


Для вашей конкретной ситуации, чтобы можно было использовать parallel, вам необходимо:

  • Отрегулировать скрипт Python таким образом, чтобы он принимал один ввод (например, имя файла) и один вывод (также возможно имя файла), оба из командной строки.
  • Узнайте, как настроить parallel, чтобы он мог получить список этих имен файлов для вставки в шаблон команды для запуска скрипта python для каждого из этих файлов по отдельности.
...