首页 文章

多处理python没有并行运行

提问于
浏览
5

我一直在尝试使用python中的多处理模块来实现计算成本高昂的任务的并行性 .

我能够执行我的代码,但它并不是并行运行的 . 我一直在阅读多处理的手册页和foruns,以找出它为什么不工作,我还没有想出来 .

我认为问题可能与执行我创建和导入的其他模块时的某种锁定有关 .

这是我的代码:

main.py:

##import my modules
import prepare_data
import filter_part
import wrapper_part
import utils
from myClasses import ML_set
from myClasses import data_instance

n_proc = 5

def main():
    if __name__ == '__main__':
        ##only main process should run this
        data = prepare_data.import_data() ##read data from file  
        data = prepare_data.remove_and_correct_outliers(data)
        data = prepare_data.normalize_data_range(data)
        features = filter_part.filter_features(data)

        start_t = time.time()
        ##parallelism will be used on this part
        best_subset = wrapper_part.wrapper(n_proc, data, features)

        print time.time() - start_t


main()

wrapper_part.py:

##my modules
from myClasses import ML_set
from myClasses import data_instance
import utils

def wrapper(n_proc, data, features):

    p_work_list = utils.divide_features(n_proc-1, features)
    n_train, n_test = utils.divide_data(data)

    workers = []

    for i in range(0,n_proc-1):
        print "sending process:", i
        p = mp.Process(target=worker_classification, args=(i, p_work_list[i], data, features, n_train, n_test))
        workers.append(p)
        p.start()

    for worker in workers:
        print "waiting for join from worker"
        worker.join()


    return


def worker_classification(id, work_list, data, features, n_train, n_test):
    print "Worker ", id, " starting..."
    best_acc = 0
    best_subset = []
    while (work_list != []):
        test_subset = work_list[0]
        del(work_list[0])
        train_set, test_set = utils.cut_dataset(n_train, n_test, data, test_subset)
        _, acc = classification_decision_tree(train_set, test_set)
        if acc > best_acc:
            best_acc = acc
            best_subset = test_subset
    print id, " found best subset ->  ", best_subset, " with accuracy: ", best_acc

所有其他模块都不使用多处理模块并且工作正常 . 在这个阶段,我只是测试并行测试,甚至没有尝试获得结果,因此进程和共享内存变量之间没有任何通信 . 每个进程都使用一些变量,但它们是在生成进程之前定义的,所以据我所知,我相信每个进程都有自己的变量副本 .

作为5个进程的输出,我得到了这个:

importing data from file...
sending process: 0
sending process: 1
Worker  0  starting...
0  found best subset ->   [2313]  with accuracy:  60.41
sending process: 2
Worker  1  starting...
1  found best subset ->   [3055]  with accuracy:  60.75
sending process: 3
Worker  2  starting...
2  found best subset ->   [3977]  with accuracy:  62.8
waiting for join from worker
waiting for join from worker
waiting for join from worker
waiting for join from worker
Worker  3  starting...
3  found best subset ->   [5770]  with accuracy:  60.07
55.4430000782

4个进程执行并行部分大约需要55秒 . 仅使用1个进程进行测试,执行时间为16秒:

importing data from file...
sending process: 0
waiting for join from worker
Worker  0  starting...
0  found best subset ->   [5870]  with accuracy:  63.32
16.4409999847

我在python 2.7和Windows 8上运行它

EDIT

我在ubuntu上测试了我的代码并且它工作正常,我猜它与Windows 8和python有关 . 这是ubuntu上的输出:

importing data from file...
size trainset:  792  size testset:  302
sending process: 0
sending process: 1
Worker  0  starting...
sending process: 2
Worker  1  starting...
sending process: 3
Worker  2  starting...
waiting for join from worker
Worker  3  starting...
2  found best subset ->   [5199]  with accuracy:  60.93
1  found best subset ->   [3198]  with accuracy:  60.93
0  found best subset ->   [1657]  with accuracy:  61.26
waiting for join from worker
waiting for join from worker
waiting for join from worker
3  found best subset ->   [5985]  with accuracy:  62.25
6.1428809166

我将从现在开始使用ubuntu进行测试,但是我想知道为什么代码在Windows上不起作用 .

1 回答

  • 2

    请务必阅读 multiprocessing 手册中的Windows指南:https://docs.python.org/2/library/multiprocessing.html#windows

    特别是“安全导入主模块”:

    相反,应该使用if name =='__ main__'来保护程序的“入口点”:如下所示:

    您在上面显示的第一个代码段中违反了此规则,因此我没有看到更多 . 希望您观察到的问题的解决方案就像包含此保护一样简单 .

    这很重要的原因是:在类Unix系统上,子进程是通过分叉创建的 . 在这种情况下,操作系统会创建创建fork的进程的精确副本 . 也就是说,所有状态都是由孩子从父母继承的 . 例如,这意味着定义了所有函数和类 .

    在Windows上,没有这样的系统调用 . Python需要执行在子项中创建新的Python解释器会话的相当繁重的任务,并重新创建(逐步)父项的状态 . 例如,需要再次定义所有函数和类 . 这就是为什么重型 import 机器正在Windows上的Python多处理子项目的引导下 . 当孩子进口主要模块时,这个机器开始 . 在你的情况下,这暗示了对孩子的 main() 的调用!当然,你不希望如此 .

    你可能会发现这很乏味 . 我发现令人印象深刻的是 multiprocessing 模块设法为两个非常不同的平台提供相同功能的接口 . 实际上,在进程处理方面,POSIX兼容的操作系统和Windows是如此不同,因此很难想出一个适用于这两者的抽象 .

相关问题