定时多处理脚本

时间:2019-04-04 15:45:39

标签: python python-3.x time python-multiprocessing

在使用多处理模块时,我偶然发现了一个奇怪的计时问题。

请考虑以下情形。我有这样的功能:

import multiprocessing as mp

def workerfunc(x):
    # timehook 3
    # something with x
    # timehook 4

def outer():

    # do something

    mygen = ... (some generator expression)

    pool = mp.Pool(processes=8)

    # time hook 1
    result = [pool.apply(workerfunc, args=(x,)) for x in mygen]
    # time hook 2

if __name__ == '__main__':
    outer()

我正在利用时间模块对函数运行多长时间有任意感觉。我成功创建了8个独立的进程,这些进程无错误终止。工人完成作业的最长时间约为130毫秒(在时间钩3和4之间测得)。

我期望(因为它们并行运行)挂钩1和挂钩2之间的时间大约相同。令人惊讶的是,结果是600毫秒。

我的机器有32个内核,应该能够轻松处理。谁能给我提示时间差异的来源?

谢谢!

2 个答案:

答案 0 :(得分:1)

由于您使用的是多处理而不是多线程,因此性能问题与GIL(Python的全局解释器锁)无关。

我找到了一个有趣的链接,并通过示例进行了说明,您可以在此答案的底部找到它。

  

GIL不会阻止进程在其他进程上运行   机器的处理器。它只允许一个线程在   一次进入解释器。

     

因此,多处理而非多线程将使您实现真正的   并发。

     

让我们通过一些基准测试了解这一切,因为只有这样   将使您相信上面所说的。是的,那应该是   学习方式-体验体验,而不是仅仅阅读或   理解。因为如果您经历过一些事情,   论点可以说服您反对的想法。

var users: [User]! = [User]()

override func viewDidLoad() {
        super.viewDidLoad()

        Alamofire.request(url2).responseJSON { response in
            switch response.result {
            case .success(let value):
                guard let jsonArray = value as? [[String: Any]] else { return }
                self.users = jsonArray.compactMap(User.init)
                print(self.users!) // works

                // call function here!
                self.usersLoaded()
            case .failure(let error):
                print(error)
            }
        }
}

func usersLoaded() {
        print(users!)
}

其他信息

Here,您可以找到此信息的来源以及更详细的技术说明(奖金:其中还有Guido Van Rossum的引文:))

答案 1 :(得分:1)

您正在使用pool.apply阻止了此操作。改用pool.apply_async,然后函数调用将全部并行运行,并且每个函数调用将立即返回AsyncResult对象。您可以使用此对象检查处理过程何时完成,然后也可以使用此对象检索结果。