Run move and collect functions in parallel

조회 수: 3 (최근 30일)
Christopher Saltonstall
Christopher Saltonstall 2025년 2월 24일
댓글: Raymond Norris 2025년 2월 28일
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일
편집: 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