Skip to content

multiprocessing parallelization and deep copy gives unexpected results #563

@augeorge

Description

@augeorge

Hello,

I am trying to run tellurium / roadrunner simulations in parallel to do parameter sweeps/estimation but get unexpected results. I can sort of get around this by creating a wrapper function that loads a new roadrunner model before simulation, but this is slow if done for a large number of iterations. I noticed similar problems when doing copy.deepcopy(rr_model). Is there a best practice or other work-around for this issue?

Below is a simple example - the parallel pool gives incorrect results.

import numpy as np
import tellurium as te
import roadrunner
import copy
from sklearn.metrics import mean_squared_error as mse
import multiprocessing as mp
import sys
import os


print(f'tellurium version: {te.__version__}')
print(f'roadrunner version: {roadrunner.__version__}')
print(f'python version: {sys.version}')
print(f'OS version: {os.uname()}')


def f(k, y_true, rr_model):
    rr_model.resetToOrigin()
    rr_model.k1 = k[0]
    rr_model.km = k[1]
    y_pred = rr_model.simulate(0, 30, 200, ['time', 'Xo', 'S'])['S']
    return mse(y_true,y_pred)


def f_wrapper(k, y_true, rr_string):
    rr_model = te.loada(rr_string)
    return f(k, y_true, rr_model)


rr_string = '''
  $Xo -> S;   Xo/(km + S^h);
  S -> $w;  k1*S;

    # initialize
    h = 1;   # Hill coefficient
    k1 = 1;  km = 0.1;
    S = 1.5; Xo = 2

    at (time > 10): Xo = 5;
    at (time > 20): Xo = 2;
'''

rr_1 = te.loada(rr_string)
y_true = rr_1.simulate(0, 30, 200, ['time', 'Xo', 'S'])['S']
ks = [[0.1,0.01], [1, 0.1], [10,1]]

mse_serial = [f_wrapper(k, y_true, rr_string) for k in ks]
mse_serial2 = [f(k, y_true, rr_1) for k in ks]

p = mp.Pool(processes=2) 
mse_parallel = np.array(p.starmap(f_wrapper, [(k, y_true, rr_string) for k in ks]))
p.close()

p = mp.Pool(processes=2) 
mse_parallel2 = np.array(p.starmap(f, [(k, y_true, rr_1) for k in ks]))
p.close()

print(f'MSE - serial w/ wrapper: {mse_serial}')
print(f'MSE - serial w/o wrapper: {mse_serial2}')
print(f'MSE - parallel w/ wrapper: {mse_parallel}')
print(f'MSE - parallel w/o wrapper: {mse_parallel2}')

output:

roadrunner version: 2.2.1
python version: 3.7.14 (default, Sep  8 2022, 00:06:44) 
[GCC 7.5.0]
OS version: posix.uname_result(sysname='Linux', nodename='db9181e5dc3c', release='5.10.133+', version='#1 SMP Fri Aug 26 08:44:51 UTC 2022', machine='x86_64')
MSE - serial w/ wrapper: [12.267022835506769, 0.0, 2.0494559584927714]
MSE - serial w/o wrapper: [12.267022835506769, 0.0, 2.0494559584927714]
MSE - parallel w/ wrapper: [12.26702284  0.          2.04945596]
MSE - parallel w/o wrapper: [0. 0. 0.]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions