Run move and collect functions in parallel

3 次查看(过去 30 天)
I have a translation stage that I want to move over a set of positions. While the stage is moving I want to record data collected from an oscilliscope. The data is collected in a function using a while loop that periodically queries the buffer of the oscilliscope. The timing of the data read and stage movement are NOT synced. So I would like to continously collect data while the stage is moving and then stop once the stage finishes its motion. How can I do this using parpool and parfeval.
Conceptual code follows
parpool('Processes',1)
points = linspace(1,10,100); %positions to move translation stage
movePos(points) %move the stage to each point
parfeval(@getData,0,D) %read data from the oscilliscope while stage is moving
function data = getData(opts) %get data from the oscilliscope
data = [];
while isStageMoving %collect data while the stage is moving
datatemp = readOscope; %read segment of data
data = [data datatemp]; %concatonate data as it is collected
end
end
function movePos(points) %move the translation stage
isStageMoving = 1;
send(D,isStageMoving) %send to getData function to start data collection
nPoints = length(points) %loop over the positions that I want to move stage
for iPoints = 1:nPoints
movestage(points(iPoints))
end
isStageMoving = 0;
send(D,isStageMoving) %send to getData function to stop data collection
end

回答(1 个)

Raymond Norris
Raymond Norris 2025-2-25
@Christopher Saltonstall here's an approach using spmd with two workers.
% function saltonstall
% 1. How is "D/opts" assigned and used?
% 2. What are we doing with "data" in getData()?
% 3. Does movePos need to return anything or does movestage do everything?
% 4. Can we block MATLAB while this spmd block is running or should it be
% non-blocking (this could be done)?
parpool("Threads",2);
spmd
if spmdIndex==1
% Move the translation stage
% Kick start reading Oscope on worker 2
spmdSend("start",2)
points = linspace(1,10,100);
nPoints = length(points);
for iPoints = 1:nPoints
movestage(points(iPoints))
end
% Signal worker 2 to stop reading Oscope
spmdSend("stop",2)
elseif spmdIndex==2
% Get data from the oscilliscope
% Get the signal from worker 1 to start
spmdReceive(1);
data = [];
while true
% Get data from the oscilliscope
datatemp = readOscope();
data = [data datatemp]; %#ok<AGROW>
if spmdProbe
% Got a signal, should we stop?
cmd = spmdReceive(1);
if strcmp(cmd,"stop")
break
end
end
end
end
end
% Pull the data from worker 2 and plot it
ldata = data{2};
plot(ldata)
  2 个评论
Christopher Saltonstall
编辑:Christopher Saltonstall 2025-2-28
This is great thank you. I updated it to run and test that it works without hardware.
What is the spmdProbe? That seem useful for adding an abort. This is going into a GUI. It would be nice to have an abort button to stop the measurements if there is an issue.
clear
close all
poolobj = gcp('nocreate');
if isempty(poolobj)
poolobj = parpool('Threads',2);
else
poolsize = poolobj.NumWorkers
end
D = parallel.pool.DataQueue;
spmd
if spmdIndex==1
% Move the translation stage
% Kick start reading Oscope on worker 2
spmdSend("start",2)
points = linspace(1,10,100);
nPoints = length(points);
for iPoints = 1:nPoints
%movestage(points(iPoints))
disp(['Point ' num2str(iPoints) ': ' num2str(points(iPoints))])
pause(0.25)
end
% Signal worker 2 to stop reading Oscope
spmdSend("stop",2)
elseif spmdIndex==2
% Get data from the oscilliscope
% Get the signal from worker 1 to start
spmdReceive(1);
data = [];
while true
% Get data from the oscilliscope
t = -pi:0.01:pi;
datatemp = rand(1)*sin(t + rand(1)*pi);
data = [data datatemp];
pause(0.03)
if spmdProbe
% Got a signal, should we stop?
cmd = spmdReceive(1);
if strcmp(cmd,"stop")
break
end
end
end
end
end
% Pull the data from worker 2 and plot it
ldata = data{2};
plot(ldata)
Raymond Norris
Raymond Norris 2025-2-28
@Christopher Saltonstall if the workers need to send data back to the MATLAB client to update a UI in "real time", I would suggest you look at Receive Communication on Workers -- it's a good working example of what you probably want. A couple of comments:
  • The example is running the same function on each worker. Instead of running a for-loop to spawn the same future on each worker, call parfeval twice, each with a different function to run on the worker (i.e., translation and oscope).
  • The client is responsible for kicking things off and stopping. Worker 1 is not instructing Worker 2 to do something (if that's what you want). If you have the R2025a prerelease, you can read about pollable dataqueues between workers (where Worker 1 could instruct Worker 2 to do something).

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Parallel Computing Fundamentals 的更多信息

产品


版本

R2024b

Community Treasure Hunt

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

Start Hunting!

Translated by