Just an additional comment: some of you may give me the advice of not refreshing the plot at each iteration to make things faster or to check on some simulink optimization tips for speed performance. I have already done that but the improvement was not enough.
Parallel processing to update plot
26 views (last 30 days)
Show older comments
Hello all and thanks in advance for reading this question.
I need to run a simulation in a simulink loop. The loop involves that at each iteration a plot is updated according to the results. This makes the simulation to run to slow. I want to use parallel processing to update the plot according to the simulation results by using another core of my CPU. For this purpose, I have been playing around using the batch command and parfor command without much success.
I wonder if anybody can give me some hints on what is the best way to address this. It would be like a separate process that at each iteration reads some numerical values from the simulink loop, and updates the plot using another core. I guess the communication between processes could be achieved with some global variables. So basically it will be a separate script to update the plot according to these variables. And this script needs to run in such a way that it wont not slow down noticeably the simulink loop and vice-versa.
Thanks a lot, Mindra
Accepted Answer
Edric Ellis
on 14 Dec 2015
It's possible that you might be able to use parfeval to achieve this. You cannot use global variables for the communication, as pointed out by Walter. parfeval is very similar to batch, except that it uses workers from your parallel pool - and therefore the overheads of running stuff are typically much lower. For instance, you could keep the Simulink model open on the worker between runs.
Following on from Walter's suggestion, you need a function that calls sim. Then, on your MATLAB client, you call parfeval to invoke that function on a worker. The client then waits for completion of the work - perhaps using fetchNext, and then retrieves the results. The client must update the plot.
7 Comments
Walter Roberson
on 15 Dec 2015
Make the first parfeval call. Enter a loop of waiting for a result, copying off whatever info you will need to plot with, start another parfeval for the next iteration, then while it is executing update the plot with the results just recorded.
Unless your plot is very dense or takes a lot of calculation after the sim() call has returned, chances are that the overhead of using the parallel worker will exceed the amount of work needed for the plotting and that you will find this arrangement to be slower than if you had not done parallel work at all.
More Answers (3)
Walter Roberson
on 13 Dec 2015
You cannot use global variables to communicate between workers. Global variables are not transferred to the workers or back from the workers.
Workers cannot update the graphics display.
Batch... that might work.
3 Comments
Walter Roberson
on 13 Dec 2015
The batch processes would run sim() and return results (pulling them out of the function workspace and returning them if necessary.) The process that created the batch would be monitoring the returns and plotting the values as they become available.
I have not looked at this much, but I do know that it is possible to examine the returns before the entire batch is complete. It might take me a while to find appropriate documentation (I have not read much about batch.)
kendur
on 5 Jun 2018
I think one possible solution you can apply is that you use two processes: First one takes data and save into files with names followed by order numbers such as "name_00.dat, name_01.dat, ..." after every data block transferred, the other one checks if the order number is updated by finding the file name and refresh the plot.
0 Comments
Emory Salberg
on 24 Mar 2021
Edited: Emory Salberg
on 24 Mar 2021
Workaround for passing variables. Look up "matlab memory mapping". Works well for communicating between applications. May help you too.
I was struggling for a while on a similar problem and this was the best solution. Only takes ~1ms to grab data.
%%%%%%%%%%
disp("IN PID2...");
tempv(1,3:5) = [R2_phidot_error(pidIdx2,3:5)];
out_msg = sprintf("%.1f," , tempv(1,:));
out_msg = strip(out_msg,'right',','); % strip final comma
out_msg = strcat("<"+out_msg,">");
disp('PID2_out: '+out_msg);
fileID = fopen('fromMatlab2.txt','w');
fwrite(fileID, out_msg,'char');
fclose(fileID);
disp("EXIT PID2...");
%%%%%%%%%%%%%
function msgReceived2(msg)
try
global readIdx2 finishR2 sOfVector
global R2_SumT R2_ENC R2_E1 R2_E2 R2_E3 R2_Q3 R2_Q4 R2_Q5 R2_FM
global Mymsg
msgin = msg;
Mymsg = msgin;
msgin2 = char(extractBetween(msgin,"<",">"));
msginCell = str2double(strsplit(msgin2,','));
R2_SumT(readIdx2) = msginCell(1);
R2_E1(readIdx2) = msginCell(2);
R2_E2(readIdx2) = msginCell(3);
R2_E3(readIdx2) = msginCell(4);
R2_ENC(readIdx2,1:3) = [R2_E1(readIdx2),R2_E2(readIdx2),R2_E3(readIdx2)];
R2_Q3(readIdx2) = msginCell(5);
R2_Q4(readIdx2) = msginCell(6);
R2_Q5(readIdx2) = msginCell(7);
R2_FM(readIdx2) = msginCell(8);
if(readIdx2>=sOfVector)
finishR2 = 1;
end
readIdx2 = readIdx2 + 1;
catch
wut = 0;
end
end
1 Comment
Emory Salberg
on 24 Mar 2021
You will be essentially writing a vecotor with known delimiters to a .txt file and then reading in values from another file. The file is never 'opened' so it saves a lot of time as you are directly reading/writing from the memory.
Also, forgot to enclude how to read the files. Its usuful to keep all of your files within the same workspace as well. Note, i was passing data to and from a python terminal running in Visual Studious, hence the 'fromPython2.txt'.
msgin=textread('fromPython2.txt','%s');
Best,
See Also
Categories
Find more on Interactive Control and Callbacks in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!