[多处理]中每个进程的数组都需要一个包含所有子列表的列表

时间:2017-12-10 01:45:44

标签: python arrays parallel-processing multiprocessing

如果有多个进程并行工作,我正在做一个程序。

对于每个进程,我想收集一些信息,然后在程序结束时,我希望将这些信息写入二进制文件。

我的一切工作正常(并行的东西和书面文件的东西),但是我收集的信息有问题......

我正在尝试将信息保存在multiprocessing.Array中,但事实是,似乎每个进程都在创建自己的数组。

当流程完成他们需要做的事情时,我打印了数组,以便我可以看到发生了什么,并打印出来:

['6554,a,0.109375,2;', '6554,c,0.099609375,2;']
['6557,g,0.109375,2;']
['6555,b,0.099609375,2;', '6555,f,0.109375,2;']
['6556,d,0.109375,2;']
[]

注意:字符串是我从流程中收集的信息。

有什么问题?
我有一个很长的代码,所以我试着尽我所能地解释自己。

-------------------------更新--------------------- --------
我正在做的项目接收一个或多个文件,并将该文件压缩成zip文件。当多个文件有多个进程时,每个进程在压缩时从文件中收集信息,并将其保存到multiprocessing.Array。 最后,我调用了另一个函数,该函数使用该数组中的信息写入二进制文件。

我期待这样一个数组(list):

['6554,a,0.109375,2;', '6554,c,0.099609375,2;', '6557,g,0.109375,2;', '6555,b,0.099609375,2;', '6555,f,0.109375,2;', '6556,d,0.109375,2;']

4 个答案:

答案 0 :(得分:1)

您必须考虑在创建新流程时,此子流程会获得自己的,新的和不同的地址空间。在空间意味着空间存储所有变量等。

  Process 1            process 2-child process
  result = []              result = []
                              |
                              |
                              |
                              ↓
                          result = [x1,x2,x3]  --> xi are the values that you want to overwrite.

你必须考虑在这种情况下结果是一个全局变量(我没有关于你的代码的信息,但我希望你可以理解共享数据和变量的要点)。请注意,子进程将在另一个地址内存中复制全局变量。所以,现在我们已经分离了一个结果变量的副本,因此当你运行你的函数时(在我的情况下为square函数),它只是在子进程中更新副本。所以,这就是问题所在。但是,我该如何解决?通过共享内存。我知道你知道,但对我来说更好,并且你要澄清这一点     分享内存

     Process 1      process 2-child process

         |             | 
         |             |
         |             |
         ↓             ↓
     result = [x1,x2,x3]  --> xi are the values that 

现在,我确信你知道。但解决方案不仅仅是使用多处理.Array(' i' 4) - >你必须指定你的数据类型,在我的例子中是整数和大小,例如4 您必须考虑到普通数组的函数不能与多处理数组函数重合。 我建议你不要忘记process.join。

     import multiprocessing

     def calc_square(numbers, result):
         for idx, n in enumerate(numbers):
              result[idx] = n*n

     if __name__ == "__main__":
         numbers = [2,3,5]
         result = multiprocessing.Array('i',3)
         p = multiprocessing.Process(target=calc_square, args=(numbers, result))

      p.start()
      p.join()

      print(result)
祝你好运!

请注意,如果您正在使用队列,则只应在函数参数中添加q(随机名称)并放入函数q.put(n * n) 在主过程中添加 q = multiprocessing.Queue() p = multiprocessing.Process(target = calc_square,args =(numbers,q))。如果你想播种所发生的事情,只需添加,而q.empty()不是False:print(q.get())

答案 1 :(得分:1)

这篇文章没有授予通用的一刀切,但鉴于上面发布的信息,这种方法除了所要求的一组功能外什么也没做:

只需做什么,而不是更多: ( otherwise you will pay way more than receive )

a)处理必须执行fileIO输出(压缩文件)
b)处理必须向中央代码报告结果/状态
c)处理不交换任何附加信息或同步

让我们模拟这样的处理:

>>> def aFunToProcessGivenSTRING( aString2PROCESS = "<aStringNotPassedOnCALL>" ):
...     time.sleep( 5 ) # emulate doing compression "efforts"
...     #               # ( yes, w/o loading a CPU-core )
...     return ( "[pid:{0:}]->( {1:} )".format( os.getpid(),
...                                             aString2PROCESS
...                                             )
...               )

让我们模拟一下&#34; 任务&#34;对于此类aFunToProcessGivenSTRING()

 aListOfTaskSTRINGs = [ '6554,a,0.109375,2;',
                        '6554,c,0.099609375,2;',
                        '6557,g,0.109375,2;',
                        '6555,b,0.099609375,2;',
                        '6555,f,0.109375,2;',
                        '6556,q,0.109376,2;',
                        '6558,r,0.109375,2;',
                        '6559,s,0.109376,2;',
                        '6553,t,0.109375,2;',
                        '6553,d,0.109375,2;',
                        'Some more Meat for Dr.Jackson',
                        'The last but not the least...'
                        ]

对于数据驱动的并行性,使用apply()的异步版本multiprocessing.Pool()内置函数的最轻量级方法就像这样:

import  multiprocessing, os, time
aPool = multiprocessing.Pool( 2 )    # Here, allow 2-Process-streams to take place

print( aPool.map( aFunToProcessGivenSTRING, aListOfTaskSTRINGs ) )

['[pid:12387]->( 6554,a,0.109375,2; )', '[pid:12388]->( 6554,c,0.099609375,2; )', '[pid:12387]->( 6557,g,0.109375,2; )', '[pid:12388]->( 6555,b,0.099609375,2; )', '[pid:12387]->( 6555,f,0.109375,2; )', '[pid:12388]->( 6556,d,0.109375,2; )', ..., '[pid:12387]->( Some more Meat for Dr.Jackson )'
 '[pid:12388]->( The last but not the least... )'
  ]

通过报告的&#34;远程&#34; - Process - #s检查2 os.getpid()个实例。

如果不打算进行其他交互,这应该最适合您的文件压缩项目。

&#34;大&#34; .Pool() - 实例应该得到吗?

嗯,这需要更深入地了解资源映射。鉴于您的处理与fileIO交互,硬件级别可能存在一些瓶颈(磁盘硬件使用纯 - [SERIAL] - 排列的原子文件块,位于物理4D位置:PLATE:CYL:HEAD:SEC和as这样的磁盘无法从更多的这样的4D位置读取#34;(确定,控制器电梯优化器有很多帮助,缓存也可以),但是没有进一步的性能限制[CONCURRENT] - 任务安排将永远克服。)

multiprocessing.Pool() - 映射的任务已经想要使用某些进程映射的并行性(以及某些模块函数)时,会出现典型的(和负面的)惊喜。产生一个.Pool()实例,覆盖&#34;只是&#34; - 足够的可用CPU核心总是比#34;超大&#34; .Pool(),然后在等待O / S调度实际上由CPU分配的任务时咳嗽,因为有多个进程而不是空闲的CPU核心。如果.Pool() - 映射函数产生它们自己的Process - 实例,那么&#34;窒息&#34;多次恶化。

类似的碰撞资源是内存。如果进程到运行需要一定量的内存,明智的容量规划应该适当考虑到这一点,因为没有人会喜欢流程来让O / S几乎无休止地交换。

所以,仔细的资源规划和“足够的”#34;资源映射是实现最高性能的一种方式。 &#34;窒息&#34;流程流程始终是这种以绩效为导向的工程实践的不良信号。永远不要低估a systematic approach to testing and benchmarking on scales, that are close to your use-case - if interested in more details about the actual costs of instantiations, under different python tools, this read may give you directions to follow.

答案 2 :(得分:0)

与线程不同,Python进程不共享内存。但是有一些例外,您可以尝试使用multiprocessing.Array作为共享状态数据结构,看看它是否像您期望的那样。
阅读有关多处理here

的更多信息

答案 3 :(得分:0)

<强> [解决]

对于那些试图帮助的人,非常感谢你们,你们都给了我一些想法,我终于做到了。

我使用了multiprocessing.Manager()。我这样用过:

with Manager() as manager:
    info = manager.list()
    proc = []
    info2 = []

    if opcoes[0] == True: 
       (...)

谢谢,我希望这可以帮助有同样问题的人。