Random generator seed for parallel simulation using fast restart

16 Ansichten (letzte 30 Tage)
I'm going to perform a monte carlo simulation by simulate a simulink model thousands of times. The model are built by blocks from SimEvent-toolbox and some standard blocks.
I use one simulink function block that are calling a MATLAB-function block. In here I try to simulate the break down of sensors during one year of service in the machine (which is the rest of the model).
MATLAB-function:
function [outputPort,log] = failureRate(time,lambda,nSensors)
persistent failed failedCount
if isempty(failed)
failed = false(1,nSensors);
failedCount = 0;
rng('shuffle')
end
% Failure rate function and random variable
failRate = @(t,lam) 1 - exp(-t*lam);
r = rand(1,nSensors);
nBroken = 0;
% Check if sensors break or not
if any(r < failRate(time,lambda))
tmp = failed;
failed = max(failed, r < failRate(time,lambda));
if failedCount < sum(failed)
failedCount = sum(failed);
nBroken = sum(failed - tmp);
end
end
if all(failed)
% All sensors broken
outputPort = 2;
log = [nBroken,time];
else
% Some sensors still working
outputPort = 1;
log = [0, time];
end
end
This function is called each time an entity enters a "Entity Server"-block, which will decide which path it will go (failed sensor path or not).
I can run this model using a normal for loop using fast restart but as soon as I try to use Fast restart for any parallel computing the randomization becomes repeated.
I've tried following:
for i = 1:n
simIn(i) = Simulink.SimulationInput('SensorFailure');
simIn(i) = simIn(i).setPreSimFcn(@(x) rng('shuffle'));
end
but it does not work when Fast restart is actiaved using the parsim command. Also I've tried with and without the "SetupFnc" option in parsim (and all different combinations of these three.
out = parsim(simIn,...
'ShowSimulationManager','off',...
'ShowProgress','on',...
'TransferBaseWorkspaceVariables','on',...
'UseFastRestart','on',...
'SetupFcn',@() rng(randi(9999999)),...
'StopOnError','on');
I also tried using parfor loop but as long as fast restart is active the randomization will be repeated.
parfor i = 1:n
rng('shuffle') %tried with shuffle and randi(10000)
out = sim('SensorFailure','FastRestart','on');
data{i} = out.sensorfailed(out.sensorfailed(:,1) > 0,2);
if mod(i,10) == 0
disp(i)
end
end
Since I'm looking to run thousands of simulation and problably things will need to be redone once the results are analyzed any gain in simulation time is worth some time to investigate!
I've tried using rng('shuffle') and rng(randi(100000)) for all possible situations since I've understood that "shuffle" is not optimal for parallel computing. I've also tried these commands in the simulink models callback (initializing and start callbacks)

Akzeptierte Antwort

Niklas Larsson
Niklas Larsson am 13 Sep. 2021
After a while I managed to find a solution that solved my problem!
By adding one more input parameter to the matlab function and feeding that input with a constant value-block:
function [outputPort,log] = failureRate(time,lambda,nSensors,seed)
persistent failed failedCount
if isempty(failed)
failed = false(1,nSensors);
failedCount = 0;
rng(seed) % Initiate with seed from constant block outside of function.
end
% Failure rate function and random variable
failRate = @(t,lam) 1 - exp(-t*lam);
r = rand(1,nSensors);
nBroken = 0;
if any(r < failRate(time,lambda))
tmp = failed;
failed = max(failed, r < failRate(time,lambda));
log = [0,0];
if failedCount < sum(failed)
failedCount = sum(failed);
nBroken = sum(failed - tmp);
end
end
if all(failed)
% All sensors broken
outputPort = 2;
log = [nBroken,time];
else
% Still working
outputPort = 1;
log = [nBroken > 0, time];
end
end
Then for each simulation in the SimulationInput-object randomize the seed value as below:
seedBlockPath = 'SensorFailure/Subsystem/Simulink Function/Seed';
for i = 1:n
% Set random seed for each simulation
simIn(i) = Simulink.SimulationInput('SensorFailure');
r = randi(99999);
simIn(i) = simIn(i).setBlockParameter(seedBlockPath,'Value',num2str(r));
end
out = parsim(simIn,...
'ShowSimulationManager','off',...
'ShowProgress','on',...
'TransferBaseWorkspaceVariables','on',...
'UseFastRestart','on',...
'StopOnError','on');
  13 Kommentare
Paul
Paul am 24 Sep. 2021
Upon further thought, I'd like to change my very important assumption to be that the function failureRate() is called once per time step. So the variable step discrete solver should work fine as long as
the function failureRate keeps track of (or gets an input that is) the dt on each call, and
the dt on every time step is small enough so that the model still achieves a good approximation to the exponential distribution.
Niklas Larsson
Niklas Larsson am 27 Sep. 2021
I guess that would work too if, as you say, the dt inbetween the calls are small enought. For my case I dont think it is.
Either way, thank you very much for your time and expertise!

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Abdolkarim Mohammadi
Abdolkarim Mohammadi am 10 Sep. 2021
Bearbeitet: Abdolkarim Mohammadi am 10 Sep. 2021
I do not know the solution to your problem, but I just want to mention that I faced a problem with SimEvents and parsim() with fast restart a while ago in R2020a, and I wrote about it here.
They reported it as a bug report here.
But the problem persists in R2021a. Maybe your problem relates to this bug.
  1 Kommentar
Edric Ellis
Edric Ellis am 13 Sep. 2021
That bug reports indicates the problem was fixed in R2020b. If you can reproduce your problem in R2020b (or later), then something else must be going wrong - please contact MathWorks support with your reproduction steps.

Melden Sie sich an, um zu kommentieren.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by