在Matlab中实现USRP的并行控制

USRPs parallel control in Matlab

本文关键字:并行 控制 USRP 实现 Matlab      更新时间:2023-10-16

我要感谢前面的每一个人阅读本文。我有一个非常具体的问题。我需要从Matlab中同时控制三个USRP。这是我的串行解决方案:

`frameLength=180;
%transmit
R=zeros(frameLength,8000);
i = 1;j = 1;k=1;nStop = 8000;
while(j<nStop)  % three times of lenght of frame                                
step(hTx1,data1(:,i)); % Tx1 transmit data in interval i
step(hTx2,data2(:,i)); %Tx2 transmit data in interval i
[Y, LEN]=step(hRx);  %receiver recieve data from Tx1 and Tx2 (but shifted)
data=Y; %just reorganzied
if mod(i,nPacket)==0 % end of column (packet, start new packet)
    i = 0;
end
if LEN==frameLength %just reorganizing
    R(:,k)=data;
    k=k+1
    if k == nStop
        break; %end
    end
end
i = i+1;
j = j+1
end`

这种解决方案有一个问题,它不是完全同步的,因为步骤功能是串行执行的,因此在接收器上来自Tx1和Tx2的信号之间几乎没有延迟。如果我在parfor中尝试这样做,让我们假设matlabpool调用4个工作程序(核心(,它会在第一个"步骤"函数上给我错误权限,因为多个工作程序试图执行同一个函数,因此会导致冲突。步骤是访问通用软件无线电外围设备(USRP(的Matlab例程。但当一个核心已经用某个USRP的参数执行该命令时,USRP正忙,而该命令的其他调用会导致错误,这就有点复杂了。不幸的是,并行循环没有为每个核心分配单独的"步骤"命令的调度。我的问题是,如果有任何问题,如何并行化至少三个步骤的命令,以防止核心冲突?如果只有这三步命令,其余的都可以串行完成,那也没关系。在最坏的情况下,可以通过调用三个matlab实例来完成,其中每个实例控制一个USRP,并且在步骤之前,命令可以是一些外部例程(例如C中的x位计数器(来同步这些任务。

我已经尝试过使用这个信号量例程来创建屏障,让每个核心在执行step命令之前停止并等待。http://www.mathworks.com/matlabcentral/fileexchange/45504-semaphore-posix-and-windows此示例如下所示:

function init()
    (1) exitThreads = false; % used to exit func1, func2, func3 threads.
(2)cntMutexKey = 5; % mutex for doneCnt.
(3)doneCnt = 0; % func1-3 increment this when they finish.
(4)barrierCnt = 0; %global
(5)barrierKey = 7; %global
(6)paralellTasksDoneKey = 8; %global, semaphore to tell main loop when func1-3 are   done.
(7)semaphore('create', cntMutexKey, 1);
(8)semaphore('create', barrierKey, 4); %Has count of 3 for each of the three functions to execute in parallel. We want to initialize it to 0.
(9)semaphore('wait', barrierKey); %now it has 3
(10)semaphore('wait', barrierKey); %now it has 2
(11)semaphore('wait', barrierKey); %now it has 1
(12)semaphore('wait', barrierKey); %now it has 0    
(13)semaphore('create', paralellTasksDoneKey, 1);
(14)semaphore('wait', paralellTasksDoneKey); %Set it to 0.
(15)funList = {@func1,@func2,@func3};
    (16)matlabpool
(17)parfor i=1:length(funList) %Start 3 threads.
        funList{i}();
(18)end
(jump  to) mycycle(); %Now run your code.
exitThreads = true; %Tell func1-3 to exit.
end
global exitThreads
while(~exitThreads)
    barrier();
    step(hTx1,data1(:,l));
    done();
end
end
function func2()
global exitThreads
while(~exitThreads)
    barrier();
    step(hTx2,data2(:,l));
    done();
end
end
function func3()
global exitThreads Y LEN
while(~exitThreads)
    barrier();
    [Y, LEN]=step(hRx); %need [Y,LEN] global or something,  and run "parfor j=1:8000" sequentially and not in paralell.
    done();
end
end
(25)function barrier()
(26)semaphore('wait', cntMutexKey); %init to 1, after 3 cores increment to 4 it proceed    IF
(27)barrierCnt = barrierCnt+1; %changed from barrierCnt += 1
(28)if(barrierCnt == 4) %We now know that func1,func2,func3,yourcode are all at the   barrier.
    (29)barrierCnt = 0; %reset count
    (30)semaphore('post', cntMutexKey);
    (31)semaphore('post', barrierKey); %Increment barrier count, so a func will run.
    (32)semaphore('post', barrierKey); %Increment barrier count, so a func will run.
    (33)semaphore('post', barrierKey); %Increment barrier count, so a func will run.
else
    (34)semaphore('post', cntMutexKey);
    (get stuck here)semaphore('wait', barrierKey); %Wait for other threads (the barrier).
end
end
function done()
semaphore('wait', doneKey);
doneCnt = doneCnt+ 1; %changed from doneCnt += 1
if(doneCnt == 3)
    semaphore('post', paralellTasksDoneKey);
    doneCnt = 0; %Reset counter.
end
semaphore('post', doneKey);
end
function mycycle()
(19) global paralellTasksDoneKey Y LEN data
(21)for j=1:8000 % three times send and recieved frame with nPackets,  
        (22)i=1; %example is done with this loop handled sequentially.
        (23)l=1; % More complex to allow this in paralell, but its not necessary
        (24)k=1;
        (jump to) barrier(); %Want loop to stop here & allow func1,func2,func3 do to their work.
        semaphore('wait', paralellTasksDoneKey); %Wait for   func1,func2,func3 to finish.
        data=Y;
        if mod(i,nPacket)==0  %end of frame
                i = 0;
        end
        if LEN==frameLength 
                R(:,k)=data;
                k=k+1;
        end
        i = i+1;
        l=l+1;
end
end

*注:括号中的数字和跳跃表示程序的流程,从debbuger开始一步一步进行。结束程序卡在那里(35(。或者可以通过使用C中的OpenMP库来并行运行这些命令,但我没有这方面的经验,我不是那么熟练的程序员。viz[http://bisqwit.iki.fi/story/howto/openmp/#Sections][2]

很抱歉有一个稍大的文件,但我想向你展示我的解决方案(不完全是我的(,因为它对任何阅读过这篇文章并且更熟练的人都有帮助。我将感谢任何形式的帮助或建议。祝大家今天愉快。

对于这类问题,我建议使用SPMD而不是PARFOR。在SPMD中,您可以使用labBarrier来同步工人。