Is it possible make parallel processing using MEX and OpenMP on Matlab?

Hello. I am making the neural recording and processing program with Matlab. the whole process are receiving from acquisition board - Data processing - Plot updating However, the process time for updating plot is too long and it dose not use all process(threads), so I want to run parallel processing of data processing and plot updating.
my plan is that make mex code which update plots using Matlab functions(plot or set) or other C library and add OpenMP code to run on parallel. by this, Matlab main thread simultaneously run both data processing code and several threads update plots.
is it possible? before starting, please check my thinking is possible!
and i add my code. please review that and give me some advices
thanks!
% I make 4 plot objects having 8 subplots.
% timeStamps and Amplifiers have 10080 samples.
for i = 1:32
subPlot(i) = subplot(8,4,i);
if 1 <= i && i <= 8
DataRawLine1(i) = plot(subPlot(i), timeStamps, Amplifiers(1,:));
elseif 9 <= i && i <= 16
DataRawLine2(i-8) = plot(subPlot(i), timeStamps, Amplifiers(1,:));
elseif 17 <= i && i <= 24
DataRawLine3(i-16) = plot(subPlot(i), timeStamps, Amplifiers(1,:));
elseif 25 <= i && i <= 32
DataRawLine4(i-24) = plot(subPlot(i), timeStamps, Amplifiers(1,:));
end
subPlot(i).XLim = [0 10080/20000];
subPlot(i).YLim = [-500 500];
subPlot(i).XTick = [];
subPlot(i).YTick = [];
end
% This code read data from FPGA USB interface board (data acquisition board)
% datablock.Amplifiers have 60 samples. for 12 times, newdata gets 720 samples.
for i = 1:12
datablock.read_next(board);
save_index = (i-1)*60 + 1;
newdata(indexChannels,save_index:save_index + 59) = datablock.Chips{1,1}.Amplifiers(indexChannels,:) * 1000000; % change unit V to uV
end
% this code update plots. we have too many plots, so updating whole plots every time spend
% too much time (we have only 36ms for each cycle, read, process and update). we divide 4
% plot objects and update each objects (8 subplots) in every cycle.
if refresh == 0
set(DataRawLine1, {'Ydata'}, num2cell(Amplifiers(1:8,:),2));
pause(0.000001); % wait until plots are updated
elseif refresh == 1
set(DataRawLine2, {'Ydata'}, num2cell(Amplifiers(9:16,:),2));
pause(0.000001); % wait until plots are updated
elseif refresh == 2
set(DataRawLine3, {'Ydata'}, num2cell(Amplifiers(17:24,:),2));
pause(0.000001); % wait until plots are updated
elseif refresh == 3
set(DataRawLine4, {'Ydata'}, num2cell(Amplifiers(25:32,:),2));
pause(0.000001); % wait until plots are updated
end
refresh = refresh + 1;
if refresh == 4
refresh = 0;
end

4 Comments

Perhaps your code to update the plots can be improved substantially. There have been many threads in this forum concerning the acceleration of graphic updates. If you post the relevant part of the code, you might get a suggestion. This is even useful, if the data acquisition is solves in another process or thread.
Thanks Jan! I update my code. can you review and give me some advice? My code to update 8 subplots spends about 10 ms. i want to reduce this time or run with data processing in same time.
10 ms to update is about 100 frames per second.
What output framerate do you need?

Sign in to comment.

 Accepted Answer

For what you are attempting, probably not. Calling MATLAB API functions that allocate/deallocate memory in mex routines is generally not thread safe. Since updating plots will in all likelihood involve memory allocation/deallocation, updating multiple plots in parallel from a mex routine will likely not be thread safe and may bomb MATLAB. You would probably have better luck if you could move all of the MATLAB memory stuff outside the parallel section and just do other known thread safe stuff inside the parallel section.

4 Comments

Thanks your comments. Did you mean write/erase memory? we will just read data from memory in Mex functions to update plots, not write. is it also not thread safe?
You propose to fetch the data from an external device inside a thread. Where are you going to get the memory to store that data?
If you malloc() the memory then that would be thread safe, but you cannot pass that malloc()'d memory to MATLAB routines (to tell the plotting routines what has to be plotted) because MATLAB will assume that it has allocated the memory, but the memory will not be wrapped in the write headers for MATLAB to use it.
If the MATLAB memory allocation routines were thread-safe, then the work-around would be that you could malloc() memory as needed to load in a chunk of data, using whatever storage form was useful for efficiency, and then once you had a chunk loaded, figure out how big it is and call one of the MATLAB memory allocation routines to request that much memory with the appropriate headers, and then take the data pointer of what was returned and use it as the destination to copy from the malloc'd memory over into the memory allocated by MATLAB. You could then pass the MATLAB-allocated memory structure into MATLAB plot routines, which would (hypothetically) have no problem dealing with it.
The problem with this is that, in practice, MATLAB memory allocation routines are not entirely thread-safe. They are probably getting better that way, but what will work and what will not work in practice can change with any update to MATLAB, not always for the better.
Thanks your comment! Right now, I can`t understand all of your comments, so need more study!
Thanks again!
MATLAB variables are not just malloc()'d as needed. MATLAB variables have headers that indicate data type and sizes and usage counts and where the actual data is stored. MATLAB routines need to be passed the address of one of these data structures, not just the address of the data.
If you were to malloc() some memory for data and were to put that inside the kind of header needed by MATLAB, then MATLAB would assume that the actual memory was allocated out of the pools it is keeping, and would try to return the memory to those pools when it was finished with the call. That would get confusing because it never allocated that memory.
So, if you want MATLAB to be able to deal with data, you have to ask MATLAB for room to store the data. Unfortunately that asking is not thread safe: if two threads ask at the same time, or if one thread is freeing data while another is requesting data, then MATLAB's data pools can get corrupted.

Sign in to comment.

More Answers (1)

Is newdata pre-allocated?
newdata = zeros(max(indexChannels, 720)); % A guess, adjust to the available info
for i = 1:12
datablock.read_next(board);
save_index = (i-1)*60 + 1;
newdata(indexChannels,save_index:save_index + 59) = ...
datablock.Chips{1,1}.Amplifiers(indexChannels,:) * 1000000;
end
Try to replace pause(0.000001) by drawnow with the "limitrate", "nocallbacks" or "update" flags.
I assume that set(DataRawLine1, {'Ydata'}, num2cell(... has the same speed as a loop:
for k = 1:8
set(DataRawLine1(k), 'YData', Amplifiers(k,:));
end
But in general your screen output looks efficient already.
In theory distributing the work over 2 threads seems to be useful: One for the data acquisition, one for the display. But the communication between the parts is not easy. The part for displaying should not use a partially filled data buffer. While it is easy to let a thread run in the background, while the main routine of a MEX returns to Matlab, it is not trivial to obtain the data from this thread efficiently in real-time.

1 Comment

Thanks your comment, and also thanks to answer my ex-questions which i posted before. yes the new data are pre-allocated. I have one more question! how can i easily run another thread in background? i think use Mex code with OpenMP libray, but that is too complicated. can you advice me?

Sign in to comment.

Categories

Find more on Deep Learning Toolbox 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!