2012-02-27 5 views
5

Ранее я задавал аналогичный вопрос, но не получил полезного ответа, поэтому я постараюсь сделать все более ясным.Многопроцессорная и многопоточная обработка

Что я ищу, это запустить многопоточный или предпочтительно многопроцессорный подход к определенной команде linux. Если кто-то знаком с Picard, я хочу запустить более раннюю версию в файле bam и в то же время запустить более новую версию в том же файле bam. Идея состоит в том, чтобы проверить, насколько быстрее будет новая версия, и если она даст тот же результат.

Моя основная проблема заключается в том, что я понятия не имею, как реализовать многопроцессорность в команде Popen. Например.

cmd1 = ['nice', 'time', 'java', '-Xmx6G', '-jar', '/comparison/old_picard/MarkDuplicates.jar', 'I=/comparison/old.bam', 'O=/comparison/old_picard/markdups/old.dupsFlagged.bam', 'M=/comparison/old_picard/markdups/old.metrics.txt', 'TMP_DIR=/comparison', 'VALIDATION_STRINGENCY=LENIENT', 'ASSUME_SORTED=true'] 
cmd2 = ['nice', 'time', 'java', '-Xmx6G', '-jar', '/comparison/new_picard/MarkDuplicates.jar', 'I=/comparison/new.bam', 'O=/comparison/new_picard/markdups/new.dupsFlagged.bam', 'M=/comparison/new_picard/markdups/new.metrics.txt', 'TMP_DIR=/comparison', 'VALIDATION_STRINGENCY=LENIENT', 'ASSUME_SORTED=true'] 

c1 = subprocess.Popen(cmd1, stdout=subprocess.PIPE) 
c2 = subprocess.Popen(cmd2, stdout=subprocess.PIPE) 

А потом у меня есть функция таймера:

def timeit(c): 
    past = time.time() 
    results = [c.communicate()] 
    present = time.time() 
    total = present - past 
    results.append(total) 
    return results 

То, что я хочу сделать это:

p = Process(target=timeit, args=(c1,c2)) 
p.start() 
p.join() 

Однако я получаю "Popen объект не итерацию" ошибка. Кто-нибудь имеет лучшую идею, чем то, что у меня есть сейчас? Я не хочу уходить совсем в другом направлении, чтобы ударить по другой стене. В итоге я хочу запустить c1 на одном процессоре и c2 на другом одновременно, пожалуйста, помогите!

+0

Почему вы хотите запускать их одновременно? Я сомневаюсь, что вы получите значимые результаты. –

+4

Рассматривали ли вы их последовательно, так что вы действительно можете имитировать сам процесс? ЦП не является единственным общим ресурсом, поэтому, если это интенсивная или интенсивная работа с памятью, у вас может быть один процесс или поток, который выигрывает и имеет вид более быстрого. – Jordan

ответ

4

Вместо прохождения subprocess.Popen (который будет запускать их последовательно, а не параллельно, когда он первый определен), передать команду:

import time 
import subprocess 
from multiprocessing import Process 

cmd1 = ['nice', 'time', 'java', '-Xmx6G', '-jar', '/comparison/old_picard/MarkDuplicates.jar', 'I=/comparison/old.bam', 'O=/comparison/old_picard/markdups/old.dupsFlagged.bam', 'M=/comparison/old_picard/markdups/old.metrics.txt', 'TMP_DIR=/comparison', 'VALIDATION_STRINGENCY=LENIENT', 'ASSUME_SORTED=true'] 
cmd2 = ['nice', 'time', 'java', '-Xmx6G', '-jar', '/comparison/new_picard/MarkDuplicates.jar', 'I=/comparison/new.bam', 'O=/comparison/new_picard/markdups/new.dupsFlagged.bam', 'M=/comparison/new_picard/markdups/new.metrics.txt', 'TMP_DIR=/comparison', 'VALIDATION_STRINGENCY=LENIENT', 'ASSUME_SORTED=true'] 

def timeit(cmd): 
    print cmd 
    past = time.time() 
    p = subprocess.Popen(cmd, stdout=subprocess.PIPE) 
    results = [p.communicate()] 
    present = time.time() 
    total = present - past 
    results.append(total) 
    return results 

p1 = Process(target=timeit, args=(cmd1,)) 
p2 = Process(target=timeit, args=(cmd2,)) 

for p in (p1, p2): 
    p.start() 
for p in (p1, p2): 
    p.join() 

ETA: В то время как выше решение является способ для выполнения многопроцессорной обработки в целом, @Jordan в точности соответствует тому, что вы не должны использовать этот подход во времени для двух версий программного обеспечения. Почему бы не запустить их последовательно?

+0

Эти задачи потенциально могут занять много времени, поэтому я бы использовал общий хост-компьютер с большей мощностью для их запуска. Если я буду запускать их последовательно (скажем, старая версия) и загрузка процессора машин была низкой, а затем через несколько часов была выпущена новая версия picard, но больше пользователей добавили задачи к хосту, заставляя его перейти на высокую нагрузку , Затем вторая задача будет работать медленнее только из-за другого трафика. Таким образом, не было бы смысла в их выборе, потому что статистика не была бы в равных условиях. –

+0

также как вы не поставили p.join() в том же цикле, что и p.start()? –

+0

также ваш гений, и я люблю тебя, это сработало. –

0

Я думаю, что что-то, как это должно работать:

p1 = Process(target=timeit, args=(c1,)) 
p2 = Process(target=timeit, args=(c2,)) 
p1.start() 
p2.start() 
p1.join() 
p2.join() 

Я не знаю, где ваша ошибка итерация хотя (что линия это?).

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

Смежные вопросы