【问题标题】:Does python's Pool() for parallelization prevent writing to global variables?用于并行化的 python 的 Pool() 是否会阻止写入全局变量?
【发布时间】:2017-12-04 11:33:12
【问题描述】:

在 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-loop 而不是 Pool.map() 方法时,一切正常,并且数组实际上包含值。当使用Pool() 函数时,变量new_array 只是停留在它的初始化状态(意味着它只包含零,因为它最初是用 初始化的)。

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

Q2:有没有其他方法可以通过并行化来解决这个问题?

【问题讨论】:

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


    【解决方案1】:

    A1:
    您的代码实际上不使用使用 global <variable> 语法声明的任何变量。尽管如此,不要试图去尝试使用它们,更不用说去分布式处理了。

    A2:
    是的,并行化是可能的,但最好在花费(好吧,浪费)努力之前彻底了解这样做的成本,这永远不能证明这样做的成本是合理的。


    为什么要从成本开始?

    您会向银行职员支付 2.00 美元,以换取一张 1.00 美元的钞票吗?

    估计没有人会这样做。

    尝试并行也是如此。

    语法是“free”和“promising”, 实际执行一个简单而美观的语法构造器的语法成本不是。期待相当令人震惊的惊喜,而不是免费获得任何晚餐。


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

    有用的工作
    您的代码实际上只在块“内部”执行一些内存访问和一些浮点操作并退出。在最近的 CPU 频率 ~2.6 ~ 3.4 [GHz] 上,这些 FLOP-s 占用少于几十个 [ns] 最多几个单位 [us]。做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] 进程不会比 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] 流程执行(使用multiprocessing.Pool)中强制执行相同数量的有用工作,将会发生什么的方法),是否可能为同一目的使用更多的 CPU 内核?

    实际的计算阶段,不会再少于T,对吧?为什么会这样?是的,从来没有。

                                   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 )
    

    间接费用 即您将始终为每次通话支付的费用(这确实是很多次)
    子流程设置 + 终止成本benchmark it 了解这些成本的规模)。内存访问成本(延迟,当您退出时,零缓存重用恰好有帮助)。


    结语

    希望视觉信息足够清晰,以便始终在决定将代码重新设计成分布式流程、拥有多核或甚至可以使用多核 [CONCURRENT] 结构。

    【讨论】:

      猜你喜欢
      • 2016-01-25
      • 2012-03-13
      • 1970-01-01
      • 2015-01-13
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多