How to communicate with two Raspberri Pis from MATLAB in parallel
4 次查看(过去 30 天)
显示 更早的评论
Using Matlab on a PC, I am trying to run two functions in parallel on two raspberry pis as shown in the example code below:
clear all;
r1 = raspi('192.168.5.120', 'pi', 'raspberry'); %tx
r2 = raspi('192.168.7.201', 'pi', 'raspberry'); %rx
delete(gcp('nocreate'));
parpool(2); %start parallel pool
parfor t=1:2
if t==1
system(r1,'python update_att.py');
disp("par1");
end
if t==2
system(r2,'python update_att.py');
disp("par2");
end
end
delete(gcp('nocreate'));
The script run through the system() function does not matter and the addresses are local. I appear to be running into a problem where each of the workers in parfor is trying to reinitialize the rasperry pi initializations defined at the start of the code as shown below:
This end up resulting in the error "The source code (path to script) for the parfor-loop that is trying to execute on the worker could not be found." caused by "Undefined function 'execute' for input arguments of type 'double'."
When I modify the code such that the raspberry pi connections are initialized within the parfor loop, the code executed properly (as shown below). However, it is necessary that I initialize my raspberry pi connections outside the parfor loop as the parfor loop itself is present in a for loop in my actual code and I desire an optimal execution time (that does not require the lengthy connection to be established each iteration of the parfor loop)
clear all;
delete(gcp('nocreate'));
parpool(2); %start parallel pool
parfor t=1:2
if t==1
r1 = raspi('192.168.5.120', 'pi', 'raspberry'); %tx
system(r1,'python update_att.py');
disp("par1");
end
if t==2
r2 = raspi('192.168.7.201', 'pi', 'raspberry');
system(r2,'python update_att.py');
disp("par2");
end
end
delete(gcp('nocreate'));
If anyone has encountered a similar problem or knows of a fix please let me know. Thanks!
0 个评论
回答(2 个)
Raymond Norris
2024-3-21
I would suggest creating the raspberry connections on the workers, before calling parfor, with parallel.pool.Constant
tx = parallel.pool.Constant( ...
@() raspi('192.168.5.120', 'pi', 'raspberry'));
rx = parallel.pool.Constant( ...
@() raspi('192.168.7.201', 'pi', 'raspberry'));
And then reference rx and tx as such
system(tx.Value,'python update_att.py');
Next, I would add a second function handle to the constant to close the connection on the workers (let's assume the raspi object has a close method to close the connection).
tx = parallel.pool.Constant( ...
@() raspi('192.168.5.120', 'pi', 'raspberry'), ...
@close);
rx = parallel.pool.Constant( ...
@() raspi('192.168.7.201', 'pi', 'raspberry'), ...
@close);
After the parfor, call
% Close Raspberry connection (i.e., close(rt.Value))
clear rx tx
Lastly, you might look at spmd instead of parfor. Conceptually, you're not running a for loop, you're running a client/server model (send/receive), but this might not fit for what you are doing.
clear all;
tx = parallel.pool.Constant( ...
@() raspi('192.168.5.120', 'pi', 'raspberry'), ...
@close);
rx = parallel.pool.Constant( ...
@() raspi('192.168.7.201', 'pi', 'raspberry'), ...
@close);
delete(gcp('nocreate'));
parpool(2); %start parallel pool
spmd
if spmdIndex==1
system(tx.Value,'python update_att.py');
disp("par1");
else
system(rx.Value,'python update_att.py');
disp("par2");
end
end
% Close Raspberry connection (i.e., close(rt.Value))
clear rx tx
delete(gcp('nocreate'));
Damian Pietrus
2024-3-21
Based on your code, it looks like you're using the Local/Processes cluster profile to run your parfor loop on. With this setup, each of the workers in the pool are their own separate process, with their own memory and Process ID which are separate from your client session. Therefore, in your first code block where you initialize the connection outside of the parfor loop, you have your client MATLAB session create a connection to the hardware. Then within the parfor loop an entirely different MATLAB process tries to use that connection, which is most likely why you get that warning. This would also be why initializing inside of the loop works, as the actual worker process establishes the connection instead of the client.
You could try to use a thread pool instead of a process pool, but I'm skeptical that the commands in your code will be supported. Give it a shot and let me know what happens:
clear all;
r1 = raspi('192.168.5.120', 'pi', 'raspberry'); %tx
r2 = raspi('192.168.7.201', 'pi', 'raspberry'); %rx
delete(gcp('nocreate'));
% Use a Thread Pool
parpool('Threads',2); %start parallel pool
parfor t=1:2
if t==1
system(r1,'python update_att.py');
disp("par1");
end
if t==2
system(r2,'python update_att.py');
disp("par2");
end
end
delete(gcp('nocreate'));
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Parallel Computing Fundamentals 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!