Python 多处理和多线程

Python 多处理和多线程,python,multithreading,subprocess,multiprocessing,Python,Multithreading,Subprocess,Multiprocessing,我以前也问过类似的问题,但没有得到有用的回答,所以我会尽量把事情弄清楚 我想要的是对某个linux命令运行多线程或最好是多处理方法。如果有人熟悉,我希望在bam文件上运行早期版本,同时在同一bam文件上运行较新版本。这个想法是为了测试新版本的速度有多快,以及它是否给出相同的结果 我的主要问题是,我不知道如何在Popen命令上实现多处理。例如 cmd1 = ['nice', 'time', 'java', '-Xmx6G', '-jar', '/comparison/old_picard/Mark

我以前也问过类似的问题,但没有得到有用的回答,所以我会尽量把事情弄清楚

我想要的是对某个linux命令运行多线程或最好是多处理方法。如果有人熟悉,我希望在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对象不可编辑”错误。有人有比我现在更好的主意吗?我不想去一个完全不同的方向,只想撞到另一面墙。总之,我想同时在一个cpu上运行c1,在另一个cpu上运行c2,请帮助

我认为这样做应该行得通:

p1 = Process(target=timeit, args=(c1,))
p2 = Process(target=timeit, args=(c2,))
p1.start()
p2.start()
p1.join()
p2.join()
我不知道你的迭代错误在哪里(是哪一行?)


另外,我认为你最好把它们分开处理。当您同时运行它们时,您将面临一个进程被赋予更多CPU时间并看起来更快的风险,即使不是这样。

而不是传递子进程。Popen(第一次定义时将以串行方式而不是并行方式运行它们)传递以下命令:


ETA:虽然上述解决方案通常是进行多处理的方法,@Jordan完全正确,您不应该使用这种方法来计时两个版本的软件。为什么不按顺序运行它们?

为什么要同时运行它们?我怀疑您是否能从中获得有意义的结果。您是否考虑过按顺序运行它们,以便您可以实际模拟流程本身?CPU不是唯一的共享资源,因此,如果这是一个内存密集型或磁盘密集型操作,您可能会有一个进程或线程胜出,并且看起来速度更快。这些任务可能需要很长时间才能运行,因此我将使用一个更强大的共享主机来运行它们。如果我按顺序运行它们(比如先运行旧版本),机器的处理器负载较低,然后在几个小时后运行新版本的picard,但更多用户向主机添加了任务,导致主机负载较高。然后,第二个任务会因为其他流量而运行较慢。因此,对它们进行计时是没有意义的,因为统计数据不会在相同的条件下进行。还有,为什么您没有将p.join()与p.start()放在相同的for循环中?哈哈,谢谢。我没有将
p.join()
放在同一个循环中,因为这样它就不会并行
p.join()
表示“等待进程p完成”。如果它们在同一个循环中,它将启动一个进程,等待它完成,启动另一个进程,然后等待它完成(因此,根本没有并行化)啊,是的,我刚刚读到这方面的内容。python文档有时很难解释。我还有一件事要问。这就是我如何简洁地展示我的结果?比如说我想打印每个函数的时间?
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()