我试图在一个大数组上进行数值积分,计算需要很长时间。我试图通过使用numba和jit decorator来加速我的代码,但是纽比·特拉普兹不支持。在
我的新想法是创建n多个线程来并行运行计算,但我想知道如何才能做到这一点,或者它是否可行?在
引用以下代码
我可以让sz[2]多个线程同时运行来调用ZO\u SteadState来计算值吗?在
for i in range(sz[1]):
phii = phi[i]
for j in range(sz[2]):
s = tau[0, i, j, :].reshape(1, n4)
[R3, PHI3, S3] = meshgrid(rprime, phiprime, s)
BCoeff = Bessel0(bm * R3)
SS[0, i, j] = ZO_SteadyState(alpha, b,bm,BCoeff,Bessel_Denom, k2,maxt,phii, PHI2, PHI3, phiprime,R3,rprime,s,S3, T,v)
正在讨论的计算。
^{pr2}$
这是我可能会做的整体想法。没有足够的上下文给你一个更可靠的例子。你必须在类中设置所有的变量。在
这是一个不使用类执行此操作的示例(假设所有内容都在本地命名空间中):
^{pr2}$另一个概念实现,流程产生流程(编辑:jit测试): 在
编辑:解释。在
这段代码中所有复杂的原因是我想做比OP要求的更多的并行化。如果只有内循环被并行化,那么外部循环仍然存在,因此对于外部循环的每次迭代,都会创建新的进程池,并对内部循环进行计算。在我看来,只要这个公式不依赖于外循环的其他迭代,我就决定并行化所有的事情:现在外循环的计算被分配给池中的进程,之后每个“外循环”进程都会创建自己的新池,生成额外的进程来执行内部循环的计算。在
不过,我可能错了,不能并行化外部循环;在这种情况下,您只能保留内部进程池。在
使用过程池可能不是最佳的解决方案,因为创建和销毁池将消耗时间。更有效(但需要手动模式)的解决方案是一次性地实例化N个进程,然后使用multiple processing Queue()将数据输入其中并接收结果。因此,您应该首先测试这个多处理解决方案是否能提供足够的加速(如果构建和销毁池的时间与
Z0_SteadyState
run相比很小,就会出现这种情况)。在下一个复杂的问题是人工的无守护进程池。守护进程用于优雅地停止应用程序:当主程序退出时,守护进程将以静默方式终止。但是,守护进程不能派生子进程。在您的示例中,您需要等到每个进程结束后才能检索数据,所以我将它们设置为非守护程序,以允许生成子进程来计算内部循环。在
数据交换:我认为,与实际计算相比,填充矩阵所需的数据量和时间是很小的。所以我使用pools和
pool.imap
函数(比.map()
快一点)。您也可以尝试.imap_unordered()
,但是在您的情况下,它不会产生显著的差异)。因此,内部池等待直到计算出所有结果并以列表形式返回它们。因此,外部池返回必须连接的列表列表。然后利用这些结果在单个快速回路中重构矩阵。在注意
with closing()
thing:在完成此语句下的操作后,它会自动关闭池,避免僵尸进程消耗内存。在另外,您可能会注意到,我在另一个函数中定义了一个奇怪的函数,在进程内部,我可以访问一些没有传递到那里的变量:
i
,phii
。发生这种情况的原因是进程可以访问全局作用域,从该作用域使用copy-on-change
策略(默认fork
模式)启动它们。这不涉及酸洗,而且速度快。在最后一个注释是关于使用
pathos
库而不是标准的multiprocessing
、concurrent.futures
、subprocess
等。原因是,pathos
使用了更好的pickling库,因此它可以序列化标准库不能序列化的函数(例如lambda函数)。我不知道你的功能,所以我用了更强大的工具来避免进一步的问题。在最后一件事:多处理与线程。您可以将
pathos
处理池从concurrent.futures
更改为标准ThreadPoolExecutor
,就像我刚开始那段代码时所做的那样。但是,在执行过程中,我的系统CPU只加载100%(也就是说,使用了一个内核,似乎所有8个内核都以15-20%的速度加载)。我不太擅长理解线程和进程之间的区别,但对我来说,进程允许使用所有内核(每个内核100%,总共800%)。在相关问题 更多 >
编程相关推荐