具有多个参数的随机过程的多重处理

multprocessing for a stochastic process with multiple arguments

我想使用多处理求解随机微分方程。简化的非并行代码如下:

import numpy as np

x       = np.zeros((2, 3, 4))                     #matrix
z       = np.random.normal(0, 1, (2,3,4))         #noise
z_array = z
for i in range(2):
    for j in range(3):
        x[i,j,0] = i
        for k in range(3):
            x[i,j,k+1] = x[i,j,k]*z_array[i,j,k]

结果是噪声z_array 和相应的矩阵x。我想在第二个循环中使用多处理。问题是我不知道如何将噪声 z 合并到并行代码中。一个天真的实现就像

import os
import numpy     as np
import functools as ft
from multiprocess import Pool 

def fun(i, k):
    x = np.zeros(4)
    x[0] = i
    for k in range(2):
        z = np.random.normal(0, 1)
        x[k+1] = x[k]*z
    return x

if __name__=='__main__':
    pool  = Pool(os.cpu_count()-1)
    x   = np.zeros((2, 3, 4))
    for i in range(2):
        result = np.array(pool.map(ft.partial(fun, i), range(3)))
        x[i] = result           
    pool.close()
    pool.join()

由于代码涉及到随机数,我不确定并行代码是否正确,也不知道如何获取噪声z。有什么想法吗?

您可以尝试预先生成噪音 z 并将其作为元组与 k 一起传递给参数。这样你就有了噪音,你不需要在函数中生成它。您还可以将元组中原始函数中带有 i 的第一个循环添加到多处理代码中的 运行 中。

对于下面的代码:

  1. 在您编写的第二个代码中,您 运行 fun 内的 k 循环为 range(2),我认为这是一个错字,我保留了它直到 range(3) 与原始代码相同
  2. 我也将第一个循环合并到多处理设置中
  3. 如果内存不是问题并且矩阵很小,请使用下面的选项,它更清晰并且原始代码和多处理代码的等效性更易于阅读。如果内存有问题,您可以只计算 fun 中较小的矩阵,然后重塑结果而不是相加(如果您需要该解决方案,请告诉我)。

主要代码:

import os
import numpy as np
from multiprocessing import Pool 

def fun(t):
    i, j, z = t
    x = np.zeros((2, 3, 4))
    x[i, j, 0] = i
    for k in range(3):
        x[i, j, k + 1] = x[i, j, k] * z[k] 
    return x


if __name__=='__main__':
    z = np.random.normal(0, 1, (2,3,4))
    pool  = Pool(os.cpu_count() - 1)
    map_args = ((i, j, z[i, j, :]) for i in range(2) for j in range (3))
    result = np.array(pool.map(fun, map_args))
    x = np.sum(result, 0)   
    pool.close()
    pool.join()