python的并行化Pool()是否会阻止写入全局变量?

时间:2017-12-04 11:33:13

标签: python-2.7 parallel-processing global-variables pool parallelism-amdahl

在python 2.7中,我试图在所有核心上分配二维数组的计算 为此,我有两个与全局范围内的变量相关联的数组,一个用于读取,另一个用于写入。

import itertools as it
import multiprocessing as mp

temp_env = 20
c = 0.25
a = 0.02
arr = np.ones((100,100))
x = arr.shape[0]
y = arr.shape[1]
new_arr = np.zeros((x,y))

def calc_inside(idx):
    new_arr[idx[0],idx[1]] = (       arr[idx[0],  idx[1]  ]
                             + c * ( arr[idx[0]+1,idx[1]  ]
                                   + arr[idx[0]-1,idx[1]  ]
                                   + arr[idx[0],  idx[1]+1]
                                   + arr[idx[0],  idx[1]-1]
                                   - arr[idx[0],  idx[1]  ]*4
                                     )
                             - 2 * a
                                 * ( arr[idx[0],  idx[1]  ]
                                   - temp_env
                                     )
                               )

inputs = it.product( range( 1, x-1 ),
                     range( 1, y-1 )
                     )
p = mp.Pool()
p.map( calc_inside, inputs )

#for i in inputs:
#    calc_inside(i)

#plot arrays as surface plot to check values

假设数组arr有一些额外的初始化,除了示例性1 - s之外还有一些不同的值,因此计算(温度的迭代计算)实际上是有意义的。

当我使用注释掉的for - 循环而不是Pool.map()方法时,一切正常,数组实际上包含值。使用Pool()函数时,变量new_array只保持其初始化状态(意味着它只包含零,因为它最初初始化时)。

Q1:这是否意味着Pool()阻止写入全局变量?

Q2:还有其他方法可以解决并行化问题吗?

1 个答案:

答案 0 :(得分:0)

A1:
您的代码实际上不使用使用 global <variable> 语法声明的任何变量。尽管如此,不要尝试使用它们,进入分布式处理的次数越少。

A2:
是的,进行并行化是可能的,但是在花费(嗯,浪费)努力之前,最好能够全面了解这样做的成本,从而无法证明这样做的成本。

为什么要开始花钱?

您是否需要向银行职员支付2.00美元才能获得一张价值1.00美元的钞票?

猜猜没人会做。

尝试并行也是如此。

语法是“免费”和“承诺”, 实际执行简单且外观漂亮的语法构造函数的语法成本不是。期待相当令人震惊的惊喜,而不是免费享用任何晚餐。

实际成本是多少?基准。基准。基准!

有用的工作
您的代码实际上只执行了一些内存访问,并在块内部进行了一些浮点操作并退出。这些FLOP-s在最近的CPU频率上只需要几个 [ns] 最多 [us] 2.6 ~ 3.4 [GHz] benchmark it:

from zmq import Stopwatch; aClk = Stopwatch()

temp_env = 20
c        =  0.25
a        =  0.02

aClk.start()
_ = ( 1.0
    + c * ( 1.0
          + 1.0
          + 1.0
          + 1.0
          - 1.0 * 4
            )
    - 2 * a
        * ( 1.0
          - temp_env
            )
      )
T = aClk.stop()

因此,四核CPU上的纯 [SERIAL] -process执行不会比约T+T+T+T(已经一个接一个地执行)更糟糕

         +-+-+-+--------------------------------- on CpuCore[0]
         : : : :
<start>| : : : :
       |T| : : :
       . |T| : :
       .   |T| :
       .     |T|
       .       |<stop>
       |<----->|
        = 4.T in a pure [SERIAL]-process schedule on CpuCore[0]

如果在现在 [CONCURRENT] -process执行的某种形式中强制执行相同数量的有用工作,将会发生什么情况(使用{ {1}}的方法),可能为了相同的目的使用更多的CPU内核?

实际的计算阶段,不会再次持续 multiprocessing.Pool ,对吗?为什么会这样?是的,永远不会。

T

开销 即。每次通话总是支付的费用(确实很多次)
子流程设置+终止费用 benchmark it 以了解这些费用的比例
内存访问成本(延迟,在您退出时,零缓存重用会发生帮助)。

结语:C / S教育没有让这个问题变得更清晰......

希望可视化消息足够清晰,以便始终开始计算应计成本,然后再决定将代码重新设计为分布式流程流,具有多核或多核的任何可实现的好处甚至可以使用多核 A.......................B...............C.D Cpu[0] <start>| : : : : |<setup a subprocess[A]>| : : . | : . |<setup a subprocess[B]>| . | +............+........................... Cpu[!0] . | : : | . |T| : | . |<ret val(s) | | +............+... Cpu[!0] . | [A]->main| | : : . |T| : . |<ret val(s) | . | [B]->main| . . . .. |<stop> |<--------------------------------------------------------- .. ->| i.e. >> 4.T ( while simplified, yet the message is clear ) 面料。