python-3.x - 通过 concurrent.futures 多处理填充 numpy 数组

标签 python-3.x numpy concurrent.futures

我正在寻求使用多处理填充大型 numpy 数组。我已经完成了文档中的并发 future 示例,但还没有获得足够的理解来修改用法。

这是我想要做的简化版本:

import numpy
import concurrent.futures

squares = numpy.empty((20, 2))

def make_square(i, squares):
    print('iteration', i)
    squares[i, 0], squares[i, 1] = i, i ** 2

with concurrent.futures.ProcessPoolExecutor(2) as executor: 
    for i in range(20):
        executor.submit(make_square, i, squares)

输出运行如下:
iteration 1
iteration 0
iteration 2
iteration 3
iteration 5
iteration 4
iteration 6
iteration 7
iteration 8
iteration 9
iteration 10
iteration 11
iteration 12
iteration 13
iteration 15
iteration 14
iteration 16
iteration 17
iteration 18
iteration 19

这很好地证明了该函数正在并发运行。但是 squares 数组仍然是空的。

填充 squares 数组的正确语法是什么?

其次,使用 .map 会是一个更好的实现吗?

提前致谢!

8/2/17
哇。所以我徘徊在 reddit-land 因为我不想因为这个问题而得到任何人。很高兴回到 stackoverflow。感谢 @ilia w495 nikitin 和 @donkopotamus。这是我在 reddit 上发布的内容,它更详细地解释了这个问题的背景。
The posted code is an analogy of what I'm trying to do, which is populating 
a numpy array with a relatively simple calculation (dot product) involving 
two other arrays. The algorithm depends on a value N which can be anything 
from 1 on up, though we won't likely use a value larger than 24.

I'm currently running the algorithm on a distributed computing system and  
the N = 20 versions take longer than 10 days to complete. I'm using dozens 
of cores to obtain the required memory, but gaining none of the benefits of 
multiple CPUs. I've rewritten the code using numba which makes lower N 
variants superfast on my own laptop which can't handle the memory 
requirements for larger Ns, but alas, our distributed computing environment 
is not currently able to install numba. So I'm attempting concurrent.futures 
to take advantage of the multiple CPUs in our computing environment in the 
hopes of speeding things up.

所以不是时间密集型的计算,而是 1600 万次以上的迭代。初始化的数组是N x 2 ** N,即上面代码中的range(16777216)。

可能根本不可能通过多处理来填充数组。

最佳答案

这里的问题是 ProcessPoolExecutor将在 内执行一个函数单独 过程。

由于这些是单独的进程,因此带有 独立的内存空间 ,您不能期望他们对您的数组( squares )所做的任何更改都会反射(reflect)在父级中。因此,您的原始数组未更改(正如您所发现的那样)。

您需要执行以下任一操作:

  • 使用 ThreadPoolExecutor ,但请注意,在一般情况下,您仍然不应该尝试在多个线程内修改全局变量;
  • 重铸您的代码,让您的进程/线程进行某种(昂贵的)计算并返回结果。

  • 后者看起来像这样:
    squares = numpy.zeros((20, 2))
    
    def make_square(i):
        print('iteration', i)
    
        # compute expensive data here ...
    
        # return row number and the computed data
        return i, ([i, i**2])
    
    with concurrent.futures.ProcessPoolExecutor(2) as executor: 
        for row, result in executor.map(make_square, range(20)):
            squares[row] = result
    

    这将产生您期望的结果:
    [[   0.    0.]
     [   1.    1.]
     [   2.    4.]
     ...
     [  18.  324.]
     [  19.  361.]]
    

    关于python-3.x - 通过 concurrent.futures 多处理填充 numpy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38309535/

    相关文章:

    python - 元组、列表和集合定义中的星号,字典定义中的双星号

    python - 在 Python 中生成多元分布(数据点)

    python - 在numpy中生成一维缩小范围数组

    python - 如何编写对 DataFrame 友好的函数

    python - ProcessPoolExecutor 使用 map 卡在大负载上

    python - 线程: function seems to run as a blocking loop although i am using threading

    python - 你如何解包不同长度的嵌套列表?

    python - 在Python中读取JSON格式的字符串

    python - 初始化对象时传递方法的最佳方式是什么

    python - 从 concurrent.futures 到 asyncio