如何并行化在python中按顺序运行许多可执行文件的“** for-loop **”?

时间:2015-11-17 19:13:58

标签: python multithreading parallel-processing multiprocessing

我有一个python脚本,它读取许多用C程序编写和编译的可执行文件。这些可执行文件没有问题。但是,当我必须在for循环中运行这些可执行文件时,我试图平行循环。

Note: prog1,prog2,prog3 must run in order.
This is a sample example, but in my real code
prog2 depends on output of prog1, and prog3 
depends on output of prog2 and so on.
I have seven executables in for loop of iteration 20,
it takes more than 2 hour to complete the process.
If i could parallize the code, it would save a lot of time.
Help would be greatly appreciated!!!!

在我的代码示例中,1运行良好,但示例2不运行。 完整代码如下:

#!/usr/bin/python

from multiprocessing import Pool
import os, sys, subprocess, math, re, shutil,copy

#function to run a program and write output to the shell
################################################################################
def run_process(name, args,):
print "--------------------------------------------------------------------"
print "Running: %s"%name
print "Command:"
for arg in args:
    print arg,
print ""
print "--------------------------------------------------------------------"
process = subprocess.Popen(args)

process.communicate()
if process.returncode != 0:
    print "Error: %s did not terminate correctly. Return code: %i."%(name, process.returncode)
    sys.exit(1)  # this will exit the code in case of error
###########################       
# example 1
#run_process("prog1.c", ['./prog1'])
#run_process("prog2.c", ['./prog2'])        
#run_process("prog3.c", ['./prog3', 'first argument'])


# example 2 (parallizing)
commands = []
for x in range(0,20):
    commands.extend(("prog1.c",['./prog1']))
    commands.extend(("prog2.c",['./prog2']))
    commands.extend(("prog3.c",['./prog3', 'first argument']))


p = Pool()
p.map(run_process, commands)

在这里,如果我运行示例1,它运行完美。但是当我尝试运行示例2时,它会出现以下错误:

    TypeError: run_process() takes exactly 2 arguments (1 given)

进一步说明:
为了创建可执行文件prog1,prog2和prog3,我编写了C代码 看起来像这样:

// to compile: gcc -o prog1 prog1.c
// to run : ./prog1
#include <stdio.h>
int main() {
printf("This is program 1\n");
return 0; }

prog2看起来完全一样。而prog3看起来像这样:

//to compile: gcc -o prog3 prog3.c 
//to run: ./prog3 'argument1'
#include <stdio.h>
int main(int argc, char ** argv) {
printf("This is program 3\n");
printf("The argument is = %s\n", argv[1]);  
return 0; }

现在,for循环中有21次迭代 在第一次迭代中,它假设它运行可执行文件prog1,prog2 ....,prog7
最后生成ouptput1.fits 在第二次交互中,它再次按顺序运行七个可执行文件并生成output2.fits 最后它创建了21个拟合文件。 我能做的是做四个功能:
func1 for loop 0 to 5
fucn2 for loop 5 to 10
func3 for loop 11到15
func4 for loop 16 to 21
然后我想在并行过程中运行这四个函数 我的问题是:如何在没有任何错误的情况下运行示例2?

3 个答案:

答案 0 :(得分:4)

Python完全为此目的构建了Pool个进程。

鉴于您需要运行X次相同的命令序列并假设命令序列可以并行运行。这意味着第N次运行可以与Nth + 1一起运行而没有任何暗示。

from multiprocessing import Pool

commands = tuple(("prog1.c",['./prog1']), ...)

def run_processes(execution_index):
    print("Running sequence for the %d time." % execution_index)

    for command in commands:
        process = subprocess.Popen(command)
        ...

p = Pool()
p.map(run_processes, range(20))

在Pyhton3上,您可以使用ProcessExecutor

每当您想要同时运行某些内容时,您需要首先了解执行边界。如果两行执行是相互依赖的,则要么在两者之间建立通信(例如使用管道),要么避免同时运行它们。

在您的情况下,命令是相互依赖的,因此同时运行它们会出现问题。但如果整个序列不是相互依赖的,那么你可以并行运行它们。

答案 1 :(得分:1)

import multiprocessing
for x in range(0,20): 
    multiprocessing.Process(target=run_process, args=("colour.c",['./cl',"color.txt",str(x) ])  
    ...

不确定我还能添加什么...

答案 2 :(得分:1)

看看Celery画布的group功能。它们允许您使用不同的参数集同时调用函数。假设您要在for循环中处理总共1000个元素。按顺序执行相同操作是非常不优化的。一个简单的解决方案是使用两组参数调用相同的函数。即便是这种简单的黑客攻击也会将处理时间缩短一半。这就是Canvas和芹菜的关键所在。