1
votes

I would like to thank to everyone in ahead for reading this. I have a very specific issue. I need to control three USRPs simultaneously from Matlab. Here is my serial solution:

`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`

This solution have one problem, its not fully synchronized because steps functions are serially executed, therefore is little delay between signals from Tx1 a Tx2 on receiver. If iI try this with parfor, lets assume that matlabpool invoke 4 workers (cores) it give me error right on first "step" function because multiple workers try to execute same function and therefore it cause collision. Step is Matlab routine to access Universal Software Radio Peripheral (USRP). But its little complicated when one core already execute that command with argument of some USRP, that USRP is busy and other call of this command causes error. Unfortunatelly there is no scheduling for parallel loops to assign individual "step" commands to each core. My question is, if is there any question how to parallelize at least three steps commands with prevent cores collision? If only these three steps commands, the rest can be done serial way, it doesn't matter. It could be done in worst case by invoking three matlab instances where every instance controls one USRP and before step command could be some external routine (like x bit counter in C for instance) to synchronize this tasks.

Ive already tried to use this semaphore routine to create barrier for every core to stop and wait before step commands. http://www.mathworks.com/matlabcentral/fileexchange/45504-semaphore-posix-and-windows This example is shown here:

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

*Note: numbers and jumps in parenthesis indicate flow of program, step by step from debbuger. End program get stuck there (35). Or it could be maybe done by using the OpenMP library in C, to run those commands in parallel, but I've non experience with that, Iam not so skilled programmer. viz [http://bisqwit.iki.fi/story/howto/openmp/#Sections][2]

Sorry for a little bit larger file, but I want to show you my solutions (not fully mine) because it can be helpful for anyone who read this and is more skilled. I will be thankful for any kind of help or advice. Have a nice day for all of you.

1
I also tried this simplified solution which can be suficient enough. <blink>nStop = 8000; funList = {@func1,@func2,@func3}; matlabpool(3) while(j<nStop) parfor l=1:length(funList) %Start 3 threads. funList{l}(); end i = i+1; j = j+1 end</blink> where functions 1-3 looks like: <blink>function func1() global final1 i step(hTx1,final1(:,i)); end</blink> But the variables from my scripts seems to be empty in functions workspaces even when I declare them like global. Does anyone know how to pass data to called func?Keyser Söze

1 Answers

0
votes

I would suggest using SPMD rather than PARFOR for this sort of problem. Inside SPMD, you can use labBarrier to synchronise the workers.