如果有多个进程并行工作,我正在做一个程序。
对于每个进程,我想收集一些信息,然后在程序结束时,我希望将这些信息写入二进制文件。
我的一切工作正常(并行的东西和书面文件的东西),但是我收集的信息有问题......
我正在尝试将信息保存在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;']
答案 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)
这篇文章没有授予通用的一刀切,但鉴于上面发布的信息,这种方法除了所要求的一组功能外什么也没做:
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()
个实例。
如果不打算进行其他交互,这应该最适合您的文件压缩项目。
.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:
(...)
谢谢,我希望这可以帮助有同样问题的人。