Как я могу запустить два подпроцесса python и получить их среды выполнения и stdout, stderr? - PullRequest
1 голос
/ 24 февраля 2012

Я пытался запустить два подпроцесса одновременно на одной машине, чтобы получить точное время выполнения.Я сравниваю две версии программного обеспечения и выполняю на них диагностику, такую ​​как время выполнения, изменение вывода и т. Д.

Первоначально у меня была одна функция, которая использует обе версии программного обеспечения в одном входном файле, и каждая выводитдругое место.Старая и новая версии перехвачены через argparser.Функция использует подпроцесс для каждой программной команды, а затем вывод передается через .communicate ().Но я знаю, что .communicate () ожидает завершения процесса, в идеале я хочу использовать .communicate () для обоих процессов одновременно, чтобы они запускались в одно и то же время и давали мне результаты всякий раз, когдапока я знаю их время выполнения.

Мой вопрос, более кратко, состоит в том, как я могу запустить два подпроцесса, каждый из которых работает по отдельности и запускается одновременно.А затем возьмите их среды выполнения и stdout, stderr?

Вот краткий пример моей функции (просто представьте, что я тестирую скорости java для какого-то файла):

def test():
    # Get start time        
    before = time.time()
    cmd1 = ['java-1.0', 'blah']
    c1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    cmd2 = ['java-1.5', 'blah']
    c2 = subprocess.Popen(cmd2, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    # Start both processes at the same time??
    results = [c1.communicate(), c2.communicate()]
    # Get total time taken
    total = round(time.time()-before, 2)
    # Print out the total time (I know its messy but its accurate)
    print "%s:%s:%s" % (int(total/60/60), int(total/60), int(total))
    c1.stderr.close()
    c2.stderr.close()
    return results

Еще один момент, который я хочуЯ хочу, чтобы они выполнялись одновременно, потому что, если я запускаю задание на мощной удаленной машине (которой я буду), тогда мне нужно, чтобы рабочая нагрузка была одинаковой при выполнении заданий, чтобы один процесс не выполнялся.заканчивайте быстрее только потому, что он бежал в другое время.

Ответы [ 3 ]

0 голосов
/ 24 февраля 2012

Тестирование во время выполнения обычно выполняется на простаивающем компьютере и повторяется несколько раз с разными входными файлами и без них, чтобы понять, как влияют кэши ОС. не приведет к более точным измерениям.

Ускорение программ на Python - это обычно случай использования правильных инструментов.Например, список - и другие понимания, как правило, быстрее, чем циклы.И использование встроенных функций, вероятно, превосходит это.Хорошим примером является " анекдот оптимизации ".Вероятно, лучшая оптимизация - это другой алгоритм.

Использование PyPy вместо CPython также может привести к значительному улучшению.

0 голосов
/ 24 февраля 2012

В этом случае, поскольку у вас нет ввода для отправки процессу, вам не нужно использовать Popen.communicate().Сам вызов Popen запускает процесс, нам не нужно Popen.communicate() для этого.Вы можете использовать Popen.poll() для проверки завершения процесса вместо использования Popen.communicate ().

while True:
    if c1.poll() is not None:
        #Stop c1's timer
    if c2.poll() is not None:
        #Stop c2's timer

Если вы хотите использовать stdout и stderr, вы можете создать 2 потока, а затем использовать Popen.communicate()запишите время.

Вы можете использовать что-то вроде этого в качестве потока:

def time_it(c):
    results.append(c.communicate())
    times.append(time.time())

Чтобы порождать потоки, позвоните

results = []
times = []
threading.start_new_thread(time_it,(c1,))
threading.start_new_thread(time_it,(c2,))
0 голосов
/ 24 февраля 2012

Если вы пытаетесь получить точные значения времени выполнения, вам нужно будет многократно запускать тест и смотреть на распределение - среднее время выполнения должно быть хорошим индикатором.Запуск обоих одновременно не поможет вам получить более точные результаты.

...