python - 使用不同数据类型的 numpy 数组进行多重处理时出现意外行为

标签 python arrays numpy multiprocessing

在使用不同数据类型的 numpy 数组进行多重处理时,我遇到了意外错误。首先,我使用 int64 类型的 numpy 数组执行多重处理,并使用 float64 类型的 numpy 数组再次运行它。 int64 按预期运行,而 float64 使用所有可用处理器(比我分配的处理器多),导致计算速度比使用单核慢。

以下示例重现了该问题:

def array_multiplication(arr):

    new_arr = arr.copy()

    for nnn in range(3):

        new_arr = np.dot(new_arr, arr)

    return new_arr

if __name__ == '__main__':

    from multiprocessing import Pool
    import numpy as np
    from timeit import timeit

    # Example integer arrays.
    test_arr_1 = np.random.randint(100, size=(100, 100))
    test_arr_2 = np.random.randint(100, size=(100, 100))
    test_arr_3 = np.random.randint(100, size=(100, 100))
    test_arr_4 = np.random.randint(100, size=(100, 100))

    # Parameter array.
    parameter_arr = [test_arr_1, test_arr_2, test_arr_3, test_arr_4]

    pool = Pool(processes=len(parameter_arr))

    print('Multiprocessing time:')
    print(timeit(lambda: pool.map(array_multiplication, parameter_arr), 
          number=1000))

    print('Series time:')
    print(timeit(lambda: list(map(array_multiplication, parameter_arr)), 
          number=1000))

将会产生

Multiprocessing speed:
4.1271785919998365
Series speed:
8.102764352000122

这是预期的加速。

但是,将 test_arr_n 替换为

test_arr_1 = np.random.normal(50, 30, size=(100, 100))
test_arr_2 = np.random.normal(50, 30, size=(100, 100))
test_arr_3 = np.random.normal(50, 30, size=(100, 100))
test_arr_4 = np.random.normal(50, 30, size=(100, 100))

结果

Multiprocessing time:
2.379720258999896
Series time:
0.40820308100001057

除了使用所有可用处理器之外,我已指定 4。下面是运行第一种情况 (int64) 和第二种情况 (float64) 时处理器使用情况的屏幕截图)。

以上是 int64 情况,其中向四个处理器分配任务,然后由一个处理器串行计算该任务。

但是,在 float64 情况下,即使指定的数量是 test_arr 的数量(即 4),所有处理器都会被使用。

我已经在array_multiplication中的for循环中尝试了许多数组大小大小和迭代次数,并且行为是相同的。我运行的是 Ubuntu 16.04 LTS,具有 62.8 GB 内存和 i7-6800k 3.40GHz CPU。

为什么会发生这种情况?提前致谢。

最佳答案

这是预期的行为。

Numpy 使用 BLAS内部(对于某些功能)是高度优化的(缓存、SIMD,并且取决于您使用的实现:多线程;一些候选实现 Atlas、OpenBLAS、MKL),并且仅因某些外部多处理(具有基于 IO 的功能)而减慢速度开销并且也可能损害缓存行为)!

现代 Ubuntu 版本默认带有多线程 BLAS 实现(早期版本仅限于 1 或 2 个线程)。

numpy 中基于 BLAS 的函数的经典示例是 np.dot()

大多数 BLAS 实现(我所知道的;看到了一些讨论 @Intel 以向 MKL 添加对离散类型的一些有限支持)only support floating-point types ,这就是为什么这两个代码表现不同的原因(一个高度优化,另一个没有;一个受到多处理的伤害,另一个则没有)。

从技术上讲,我不会称其为错误,但这是您描述的观察结果!

相关question .

关于python - 使用不同数据类型的 numpy 数组进行多重处理时出现意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46200272/

相关文章:

python - 根据另一列的数据更改时区

python - 覆盖 Django Rest ViewSets 删除行为

Python 3.3 for() 循环迭代处理时间呈指数增长?

c++ - 声明数组时 VS2008 错误预期常量表达式,但 GCC 中此代码没有错误

php - 数组搜索中的通配符

python - 使用函数给定的值初始化 numpy 数组的最快方法

python - python中的random.normalvariate()和random.gauss()有什么区别?

javascript - 有没有更简洁的方法在javascript中编写css边距字符串

python - 使用 Python 绘制蝴蝶曲线

python - 如何在 Python 中执行 C 风格类型转换?