2012-02-27 31 views
5

Tôi đã hỏi một câu hỏi tương tự trước đây, nhưng không có phản hồi hữu ích vì vậy tôi sẽ cố gắng làm cho mọi thứ rõ ràng hơn.Multiprocessing and Multithreading

Điều tôi đang tìm là chạy một phương pháp đa xử lý hoặc ưu tiên đa xử lý cho một lệnh linux nhất định. Nếu có ai quen thuộc với Picard, tôi muốn chạy phiên bản cũ hơn trên tệp bam và đồng thời chạy phiên bản mới hơn trên cùng một tệp bam. Ý tưởng là để kiểm tra phiên bản mới hơn nhanh hơn bao nhiêu và nếu nó mang lại kết quả tương tự.

Vấn đề chính của tôi là tôi không biết cách thực hiện đa xử lý trên lệnh Popen. Ví dụ.

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) 

Và sau đó tôi có một chức năng hẹn giờ:

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

những gì tôi muốn làm điều này là:

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

Tuy nhiên tôi nhận được "Popen đối tượng không iterable" lỗi. Có ai có một ý tưởng tốt hơn những gì tôi có bây giờ? Tôi không muốn đi theo một hướng hoàn toàn khác chỉ để đánh một bức tường khác. Tóm lại, tôi muốn chạy c1 trên một cpu và c2 trên cpu khác cùng một lúc, xin vui lòng giúp đỡ!

+0

Tại sao bạn muốn chạy chúng cùng một lúc? Tôi nghi ngờ bạn sẽ nhận được kết quả có ý nghĩa từ điều này. –

+4

Bạn đã xem xét việc chạy chúng tuần tự, sao cho bạn thực sự có thể bắt chước quá trình đó? CPU không phải là tài nguyên được chia sẻ duy nhất, vì vậy nếu đây là một hoạt động chuyên sâu về bộ nhớ hoặc sử dụng nhiều đĩa, bạn có thể có một quy trình hoặc chuỗi đang thắng và có giao diện nhanh hơn. – Jordan

Trả lời

4

Thay vì đi qua các subprocess.Popen (mà sẽ chạy chúng serially thay vì song song khi nó lần đầu tiên được xác định), vượt qua lệnh:

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: Trong khi giải pháp trên là cách để thực hiện đa xử lý nói chung, @Jordan chính xác là bạn không nên sử dụng phương pháp này cho thời gian hai phiên bản phần mềm. Tại sao không chạy chúng tuần tự?

+0

Các tác vụ này có thể mất nhiều thời gian để chạy, do đó tôi sẽ sử dụng máy chủ chia sẻ có nhiều quyền hơn để chạy chúng. Nếu tôi chạy chúng tuần tự (nói phiên bản cũ trước) và tải bộ vi xử lý máy thấp, và sau đó sau vài giờ, phiên bản mới của picard chạy nhưng nhiều người dùng đã thêm công việc vào máy chủ khiến nó tải lên cao . Sau đó, nhiệm vụ thứ hai sẽ chạy chậm hơn chỉ vì lưu lượng truy cập khác. Do đó sẽ không có điểm trong việc định thời gian chúng, bởi vì các số liệu thống kê sẽ không ở trong điều kiện bình đẳng. –

+0

cũng như thế nào đến bạn không đặt p.join() trong cùng một vòng lặp như p.start()? –

+0

cũng là một thiên tài của bạn và tôi yêu bạn, nó hoạt động. –

0

Tôi nghĩ rằng một cái gì đó như thế này nên làm việc:

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

Tôi không biết nơi lỗi lặp của bạn là mặc dù (cái dòng là nó?).

Ngoài ra, tôi nghĩ bạn nên chạy chúng một cách riêng biệt hơn. Khi bạn đang chạy chúng với nhau, bạn chạy nguy cơ của một quá trình được cho thêm thời gian CPU và xuất hiện để được nhanh hơn, ngay cả khi nó không phải là.