代码之家  ›  专栏  ›  技术社区  ›  Indominus

numpy矩阵代数或用于循环/列表理解的python自动利用多处理?

  •  1
  • Indominus  · 技术社区  · 7 年前

    我一直认为python列表理解并没有隐式地利用多处理和阅读堆栈上的问题(例如。 this one )也给我同样的印象。然而,以下是我的小实验:

    import numpy as np
    import time
    
    # some arbitrary data
    n = 1000
    p = 5
    X = np.block([[np.eye(p)], [np.zeros((n-p, p))]])
    y = np.sum(X, axis=1) + np.random.normal(0, 1, (n, ))
    n_loop = 100000
    
    # run linear regression using direct matrix algebra
    def in_sample_error_algebra(X, y):
        beta_hat = np.linalg.inv(X.transpose()@X)@(X.transpose()@y)
        y_hat = X@beta_hat
        error = metrics.mean_squared_error(y, y_hat)
        return error
    
    
    start = time.time()
    errors = [in_sample_error_algebra(X, y) for _ in range(n_loop)]
    print('run time =', round(time.time() - start, 2), 'seconds')
    

    当这段代码运行时,我的CPU的所有6个(物理)内核都达到了100%

    enter image description here

    更神奇的是,当我从列表理解改为for循环时,同样的事情发生了。我想是因为 .append

    start = time.time()
    errors = []
    for _ in range(n_loop):
        errors.append(in_sample_error_algebra(X, y))
    print('run time =', round(time.time() - start, 2), 'seconds')
    

    运行时间=21.29秒

    enter image description here

    有什么理论吗?

    Python 3.7.2, numpy 1.15.4

    1 回复  |  直到 7 年前
        1
  •  2
  •   MB-F    7 年前

    事实上,纯Python计算不会从中受益 多线程 . 这个 global interpreter lock (GIL)

    在Python中是可能的,因为每个进程都运行自己的Python解释器实例。这有一个性能成本:初始化和数据共享在进程之间不是免费的。通常这甚至不值得付出努力。

    对于努比来说,情况就不同了。Numpy主要由用C编写的本机函数组成。当C代码暂时不需要解释器时,它可以释放GIL并允许不同的Python线程同时运行。C代码还可以生成“非Python”线程来并行计算。这就是努比发生的事情。

    总之,无论是外部列表理解还是 for 循环并行运行,但是 np.linalg.inv 还有矩阵积 X @ beta_hat 可以在内部运行多个线程。看见 Parallel Programming with numpy and scipy 了解更多信息。