python多处理模块:使用Pool

时间:2016-04-18 23:47:17

标签: python multiprocessing cpu-usage python-multiprocessing ubuntu-server

我使用Python的多处理库来加速一些代码(最小二乘拟合scipy)。

它可以在3台不同的机器上正常工作,但它在第4台机器上显示出奇怪的行为。

代码:

import numpy as np
from scipy.optimize import least_squares
import time
import parmap
from multiprocessing import Pool

p0 = [1., 1., 0.5]

def f(p, xx):
    return p[0]*np.exp(-xx ** 2 / p[1] ** 2) + p[2]

def errorfunc(p, xx, yy):
    return f(p, xx) - yy

def do_fit(yy, xx):
    return least_squares(errorfunc, p0[:], args=(xx, yy))

if __name__ == '__main__':
    # create data
    x = np.linspace(-10, 10, 1000)
    y = []
    np.random.seed(42)
    for i in range(1000):
        y.append(f([np.random.rand(1) * 10, np.random.rand(1), 0.], x) + np.random.rand(len(x)))

    # fit without multiprocessing
    t1 = time.time()
    for y_data in y:
        p1 = least_squares(errorfunc, p0[:], args=(x, y_data))
    t2 = time.time()
    print t2 - t1

    # fit with multiprocessing lib
    times = []
    for p in range(1,13):
        my_pool = Pool(p)
        t3 = time.time()
        results = parmap.map(do_fit, y, x, pool=my_pool)
        t4 = time.time()
        times.append(t4-t3)
        my_pool.close()
    print times

对于工作的3台机器,它大致以预期的方式加速。例如。在我的i7笔记本电脑上,它给出了:

[4.92650294303894, 2.5883090496063232, 1.7945551872253418, 1.629533052444458, 
1.4896039962768555, 1.3550388813018799, 1.1796400547027588, 1.1852478981018066, 
1.1404039859771729, 1.2239141464233398, 1.1676840782165527, 1.1416618824005127]

我正在运行Ubuntu 14.10,Python 2.7.6,numpy 1.11.0和scipy 0.17.0。 我在另一台Ubuntu机器,具有类似结果的Dell PowerEdge R210和MacBook Pro Retina(此处使用Python 2.7.11,以及相同的numpy和scipy版本)上进行了测试。

导致问题的计算机是运行Ubuntu 15.10,Python 2.7.11以及上述相同的numpy和scipy版本的PowerEdge R710(两个十六进制)。 但是,我没有观察到任何加速。无论我使用什么池化,时间大约是6秒。实际上,对于2个池化来说稍微好一些,对于更多进程来说会更糟。

htop表明某些方法会产生比我预期更多的进程。

E.g。在我的笔记本电脑htop上显示每个进程一个条目(与池大小匹配),最终每个进程显示100%的CPU负载。

在PowerEdge R710上,我看到大约8个python进程用于1个池化,大约20个进程用于2个池化等,每个进程显示100%的CPU负载。

我检查了R710的BIOS设置,但我找不到任何异常。 我应该寻找什么?

编辑: 在回答评论时,我使用了另一个简单的脚本。令人惊讶的是,这个似乎是“工作”。适用于所有机器:

from multiprocessing import Pool
import time
import math
import numpy as np

def f_np(x):
    return x**np.sin(x)+np.fabs(np.cos(x))**np.arctan(x)

def f(x):
    return x**math.sin(x)+math.fabs(math.cos(x))**math.atan(x)

if __name__ == '__main__':
    print "#pool", ", numpy", ", pure python"
    for p in range(1,9):
        pool = Pool(processes=p)
        np.random.seed(42)
        a = np.random.rand(1000,1000)
        t1 = time.time()
        for i in range(5):
            pool.map(f_np, a)
        t2 = time.time()
        for i in range(5):
            pool.map(f, range(1000000))
        print p, t2-t1, time.time()-t2
        pool.close()

给出:

#pool , numpy , pure python
1 1.34186911583 5.87641906738
2 0.697530984879 3.16030216217
3 0.470160961151 2.20742988586
4 0.35701417923 1.73128080368
5 0.308979988098 1.47339701653
6 0.286448001862 1.37223601341
7 0.274246931076 1.27663207054
8 0.245123147964 1.24748778343

导致问题的机器上。产生的线程(或进程?)没有比我预期的更多。

看起来numpy不是问题,但是一旦我使用scipy.optimize.least_squares就会出现问题。

htop上使用这些流程会显示很多sched_yield()来电,如果我不使用scipy.optimize.least_squares而我也不会这样做,我也不会这样做#&# 39;即使使用least_squares,我也可以在笔记本电脑上看到。

1 个答案:

答案 0 :(得分:3)

根据here,当OpenBLAS与joblib一起使用时会出现问题。

使用MKL时会出现类似问题(请参阅here)。 这里给出的解决方案也对我有用: 添加

import os
os.environ['MKL_NUM_THREADS'] = '1'
在我的python脚本开头的

解决了这个问题。