многопроцессорность для стохастического c процесса с несколькими аргументами - PullRequest
0 голосов
/ 23 февраля 2020

Я хочу решить стохастическое c дифференциальное уравнение, используя многопроцессорность. Упрощенный непараллельный код выглядит так:

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. Я хочу использовать многопроцессорность для второго l oop. Проблема в том, что я не знаю, как включить шум 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. Есть идеи?

1 Ответ

1 голос
/ 23 февраля 2020

Вы можете попробовать предварительно сгенерировать шум z и передать его аргументу вместе с k в качестве кортежа. Таким образом, у вас есть шум, и вам не нужно генерировать его в функции. Вы также можете добавить первый l oop с i в исходную функцию в кортеже, чтобы запустить его в многопроцессорном коде.

Для кода ниже:

  1. Во втором написанном вами коде вы запустили k l oop внутри fun как range(2), что я предполагаю это опечатка, и я сохраняю ее до range(3), как в исходном коде
  2. Я включил первый l oop в настройку многопроцессорности тоже
  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()
...