Slow speed of UDP reception in Matlab - matlab

My FPGA is sending UDP packets on network using 100 mbps ethernet and a have written a MATLAB code to capture the data. The problem is i am getting very low speed in MATLAB around 50 kbps during reception. FPGA kit is connected to a gbps switch and then to PC. No internet cable in the switch.
I am pasting the matlab code below. If i try to increase the speed by increasing buffer size, the packets are dropped. current settings are through hit and trial on which i receive all data successfully. IS there any way to increase data reception speed in MATLAB?
Code:: (UDP from FPGA to Matlab)
clc
clear all
close all
u=udp('192.168.0.100','RemotePort',4660,'Localport',4661);
set(u,'DatagramTerminateMode','off');
set(u, 'InputBufferSize', 18);
set(u,'Timeout',0.1);
fopen(u);
x=tic;
for i =1:1000
a(:,i) = fread(u,18);
end
fclose(u);
delete(u);
t=toc(x);
bw = (1000*18*8)/t;
/////////////////////////////////////////////////////////
A MODIFIED VERSION OF THE ABOVE CODE (EASE OF UNDERSTANDING) + IMAGE Showing the PROBLEM
also: An image showing Data Variable with a buffer size of 20 Packets (18 bytes / Packet). Data must not be all zero as pointed in the image. It represents missed packets.
/////////////////////////////////////////////////////////
clc
clear all
close all
packet_size = 18; % Size of 1 Packet
buffer_size = 1*packet_size; % Buffer to store 1024 packets each of Packet_Size
buffer_read_count = 10; % How many times the buffer must be read
u=udp('192.168.0.100','RemotePort',4660,'Localport',4661);
set(u,'DatagramTerminateMode','off');
set(u, 'InputBufferSize', buffer_size);
set(u,'Timeout',0.5);
fopen(u);
x=tic;
for i =1:buffer_read_count
[a, count] = fread(u,buffer_size); % Read the complete buffer in one Fread()
if (count == buffer_size)
data(:, i) = a; %If Read_BYtes(Count) == BufferSize Store in Data
end
end
fclose(u);
delete(u);
t=toc(x);
bw = (buffer_read_count*buffer_size*8)/t; %Speed / BW of UDP Reception

I looked at your code and found some basic corrections, let me know if it speed up your code.
u=udp('192.168.0.100','RemotePort',4660,'Localport',4661);
set(u,'DatagramTerminateMode','off', ...
'InputBufferSize', 18, ...
'Timeout',0.1); % I think only one call of set is needed here
fopen(u);
x=tic;
% The variable a is not pre-allocated before the loop
a = zeros(YourNumberOfLine, 1000)
for ii =1:1000 % Always use ii and jj and not i and j
a(:,ii) = fread(u,18);
end
fclose(u);
delete(u);
t=toc(x);
bw = (1000*18*8)/t;

Let me summarize my comments.
Low code efficiency
As #m_power has pointed out, using i and j slows down your code by a bit. See this for more information. In Matlab, you should always use ii and jj instead.
You didn't initialize data. See how Mathworks explain this. If #1 "slows by a bit", #2 then slows a lot.
Since your code is slow, it's not guaranteed that each time FPGA sends a packet, your PC is able to find any available buffer to receive the packet.
Full buffer
if (count == buffer_size)
data(:, i) = a; %If Read_BYtes(Count) == BufferSize Store in Data
end
So if the packet is smaller than the buffer, data(:,i) = nothing? That is the most possible reason why you are getting zeros in column 3,4,and 5.
Empty buffer
Zeros in column 3, 4 and 5 may also originate from an empty buffer, if you have done the previous changes. The buffer is not guaranteed to carry something when Matlab reads it, so some for iterations may catch zero-length contents, data(:,ii) = 0.
Use a while loop to solve this issue. Only count for non-empty buffer readings.
ii = 0;
while (ii < buffer_read_count)
[a, count] = fread(u, buffer_size);
if count % non-empty reading
ii = ii+1;
data(1:count,ii) = a;
end
end
....incomplete packets?
You wait for a full buffer, because each time you want to read an entire packet? I suddenly realized it; how stupid I was!
But what you have done is keeping reading the buffer, and throwing away the data as long as it's shorter than the buffer length.
Instead, you'll need aggregate the data in each loop.
data = zeros(buffer_size, buffer_read_count);
total_size = buffer_read_count*buffer_size;
ptr = 1; % 1-D array index of data
while (ptr < total_size)
[a, count] = fread(u, buffer_size);
if count % non-empty reading
if ( (ptr+count) > total_size )
data(ptr:end) = a(1:(total_size-ptr+1));
ptr = total_size;
else
data( ptr:(ptr+count-1) ) = a;
ptr = ptr+count;
end
end
end
Test - I changed fread to a random integer generator with ii remembering how many times the buffer is read.
clear all;clc;
buffer_size = 18;
buffer_read_count = 10;
data = zeros(buffer_size, buffer_read_count);
total_size = buffer_read_count*buffer_size;
ptr = 1; % 1-D array index of data
ii = 1;
while (ptr < total_size)
count = randi(buffer_size);
a = randi(9, count, 1) + ii*10; % 10's show number of buffer readings
ii = ii+1;
% [a, count] = fread(u, buffer_size);
if count % non-empty reading
if ( (ptr+count) > total_size )
data(ptr:end) = a(1:(total_size-ptr+1));
ptr = total_size;
else
data( ptr:(ptr+count-1) ) = a;
ptr = ptr+count;
end
end
end
disp(data)
The result is
13 38 51 63 72 93 104 125 141 164
12 35 53 63 73 96 101 123 148 168
14 33 55 68 72 99 106 124 142 168
14 37 51 69 77 91 109 127 145 165
12 33 57 66 76 96 114 137 143 168
14 39 56 63 72 94 117 139 144 169
11 46 55 61 72 93 111 139 146 164
16 42 58 68 75 93 119 135 153 164
26 41 58 66 79 109 126 139 152 166
33 43 58 69 75 102 122 132 152 177
35 48 53 61 81 108 125 131 153 174
36 49 55 66 95 102 125 133 165 177
31 47 57 63 94 109 129 136 164 179
35 47 51 72 98 108 128 135 162 175
36 43 51 74 94 104 129 139 169 175
32 46 53 74 95 107 127 144 164 173
38 48 55 78 97 105 124 145 168 171
39 44 59 77 98 108 129 147 166 172
As you can see, each time the length of fread output is either equal to or less than the buffer size. But it only jumps to the next column when the current one has been completely received.

Related

How to perform reduced row echelon form on a non-square GF matrix (GF(2^8)) in matlab

%GF(2^8)
m=8
mat1 = gf([160 28 233 185 176],8);
result1 = gf([160 28 233 185 176],8)/gf([160],8)
% 1 77 174 32 220
[R,jb] = rref([1 77 174 32 220;189 244 80 245 190])
I use the result from result1 as 1st row and progressively add the next row vector [189 244 80 245 190]
% reduced row echelon
mat2 = [1 77 174 32 220;189 244 80 245 190]
a = gf([1 77 174 32 220;189 244 80 245 190],8);
r2 = a(2,:); r1 = gf(189,8) * a(1,:);
subt = r2 -r1; a(2,:)= subt./gf(122,8);
a(1,:) = a(1,:)- (gf(77,8) *a(2,:));
disp(a)
mat3 = [[1 0 101 105 110]; [0 1 163 128 97]; [157 233 247 64 118]];
m3 = gf(mat3,8);
m3(3,:)= m3(3,:) - (gf(157,8) * m3(1,:))
m3(3,:)= m3(3,:) - (gf(233,8) * m3(2,:))
m3(3,:)= m3(3,:)./ gf(29,8) .
rref works without GF(2^8). But I am unable to perform the reduction using GF(2^8) . Can someone help me to find a solution and how to proceed?
I will be using the result from the above and append another row-vector to the it. Is there any function we can solve it, instead of going step-by-step

Matlab: Reading from .txt file

I've got a .txt file with always two values per line separated by tabs:
0 0
23 69
45 108
81 158
110 253
125 357
141 492
165 606
179 753
189 983
. .
0 0
4 31
33 38
45 89
60 115
75 166
93 201
107 216
116 291
133 366
148 480
170 631
196 720
207 994
. .
0 0
19 81
33 102
46 128
72 161
138 236
178 398
197 537
210 658
220 832
. .
0 0
24 38
40 90
71 166
99 193
etc.
Always beginning with 0 0 and ending with . . (80 times)
I'd like to read all the data in with Matlab. This is my code:
% Variab
line{1} = 0;
% Open files
fid = fopen(('D:\Dokumente\Studium\8. Semester\BA\Vali mit einzelenne punkten\alle.txt'), 'rt');
% Read Data
for i = 1:80
j = 1;
line = fgets(fid);
line = textscan(line,'%f %f');
while line{1} ~= '.'
digNum{i}(j) = line{1};
gewicht{i}(j) = line{2};
line = fgets(fid);
line = textscan(line,'%f %f');
j = j + 1;
end
end
So as you can see I want the left number to be saved as digNum{upOneValueWhen'.'}{numberIn'Vector'} and the right number gewicht{upOneValueWhen'.'}{numberIn'Vector'}.
Everything works fine but when I get to digNum = 46 (second to the last "vector") {upOneValueWhen'.'} goes up a number.
I have no idea why. 'i' should only go up after '.' but for some reason it goes up at this one particular spot.
Any ideas???
Thank you so much in advance
I would try to read the entire file in one while loop, line by line, until the end of the file is reached:
% Open files
fid = fopen('test.txt');
% Read Data
i = 1;
j = 1;
while(~feof(fid))
line = fgetl(fid);
if strfind(line,'.')
i = i + 1;
continue;
end;
s = textscan(line,'%s','delimiter',' ');
digNum{i,j} = str2double(s{1}{1});
gewicht{i,j} = str2double(s{1}{length(s{1,1})});
j = j + 1;
end;
fclose(fid);
Now you can easily increment i when a . is recognized.
Furthermore, making use of str2double you would be able to put all the data into two matrices.
I think the above works as mentioned.
As mentioned the data so far does not reproduce the problem. Fortunately you should be able to solve it yourself with these steps:
Place (conditional) breakpoints in your code.
Find the last moment where things are going well, and the first moment where things have gone wrong.
Go to the last moment where things are going well, and run your code line by line, carefully look at how all variables change
This way you will quickly find the problem.

Error in for loop in matlab

I have an error in the following forloop. I know because the end value of the first for is going to be changed and it is not acceptable for Matlab to change in inside iteration. But would you have any idea how to overcome to it? By the way I used while, but does not help me at all. Data are as follow:
D = [
2.39484592826072e-05 286
4.94140791861196e-05 161
5.07906972800045e-05 163
0.000103133134300751 141
0.000142755898501384 136
0.000143741615840070 152
0.000188072960663613 177
0.000203545320971960 1
0.000269110781516704 296
0.000333161025069404 293
0.000351184122591795 167
0.000393661764751196 299
0.000469154814856272 173
0.000516662289403544 181
0.000537612407901054 156
0.000698464342131732 246
0.000848447859349023 66
0.000875283151707512 75
0.00102377583629824 68
0.00110034589129900 277
0.00110693756077989 129
0.00120680501123819 87
0.00151080017572355 78
0.00159156469379168 248
0.00190852817897233 270
0.00192106167039306 133
0.00224677708557380 258
0.00246430115488258 264
0.00288772180685041 255
0.00299392149856582 81
0.00315341807121748 242
0.00327625233716732 27
0.00362308575885149 124
0.00434568780796603 220
0.00443389247698617 239
0.00470947127244510 60
0.00474015278667278 23
0.00481651908877289 230
0.00487750364266560 53
0.00510342992049100 56
0.00513758569662983 228
0.00515453564704144 121
0.00515656244518627 232
0.00526922882200147 8
0.00547349131456174 50
0.00553337871530176 117
0.00569159206242299 18
0.00620144292620718 13
0.00630382865700000 119
0.00755647842280271 92
0.00983041839684126 40
0.00997057619578698 98
0.0102611966834032 44
0.0103337998140422 100
0.0105132461082006 37
0.0106952804631761 109
0.0107424055503829 208
0.0109630950142485 111
0.0115094667290339 105
0.0119529682389369 107];
ymin= D(:,1);
mean_value = 0.00773867192661190;
criteria = min(ymin);
kk = 1;
diff = 60;
and here is the code that I would have an error for the changing size_D which is expected.
while criteria < mean_value
if isempty(B)
ind_crt = find(min(ymin));
B(kk,:) = D(ind_crt,:);
D(ind_crt,:) = [];
kk = kk + 1;
end
criteria = min(min(D));
size_D = size(D,1);
for ii=1:size_D
if D(ii,1) == criteria
size_B = size(B,1);
for jj = 1:size_B
if abs(D(ii,2) - B(jj,2)) > diff
B(kk,:) = D(ii,:);
D(ii,:)= [];
kk = kk + 1;
end
size_D = size_D -1;
criteria = min(min(D))
end
end
end
end
Update:
Here is the error:
Attempted to access D(59,1); index out of bounds because
size(D)=[58,2].
Error in local_minima (line 50)
if D(ii,1) == criteria
Replace your for loop by a while loop, so that the code in the loop is run only if the condition ii<=size_D is verified:
ii=0;
while ii<=size_D
ii=ii+1;
%loop code
instead of the
for ii=1:size_D
%loop code

read/load parts of the irregular file by Matlab

I would like to partly load a PTX file by matlab (please see the following example)
I need to read and write the first two row (2 numbers) into 2 variables say a and b. And read and write the data from 5th row to the end into a matrix
Thanks for your help
114
221
1 0 0
1 0 0 0
-5.566405 -7.161944 -1.144557 0.197208 24 29 35
-5.560656 -7.154540 -1.137673 0.222400 29 32 39
-5.559846 -7.153491 -1.131895 0.254002 37 40 49
-5.560894 -7.154833 -1.126452 0.305013 51 54 63
-5.560084 -7.153783 -1.120633 0.290013 72 76 88
-5.561128 -7.155119 -1.115189 0.243214 105 113 134
-5.563203 -7.157782 -1.109926 0.227604 130 143 177
-5.569191 -7.165479 -1.105504 0.201602 121 140 173
-7.833616 -10.078705 -1.546952 0.130007 94 112 134
Look at the tdfread function in order to get the data into Matlab. It should be something like datafile = tdfread(filename, '\t'). Once you have that, index into the variable returned from that function like
a = datafile(1, 1);
b = datafile(2, 1);
data = datafile(5:end, :);

Selecting elements of a vector based on two vectors of starting and ending positions matlab

I would appreciate your help with the following problem in matlab:
I have a vector and I would like to select parts of it based on the following two vector of start and end indices of parts:
aa = [1 22 41 64 83 105 127 147 170 190 212 233]
bb = [21 40 63 82 104 126 146 169 189 211 232 252]
Basically I would like to perform some function on V(1:21), V(22:40),... V(233:252).
I have tried V(aa:bb) or V(aa(t):bb(t)) where t = 1:12 but I get only V(1:21), probably because V(22:40) has 19 elements compared to V(1:21) which has 22 elements.
Is there a fast way of programming this?
Put your selection in a cell array, and apply your function to each cell:
aa = [1 22 41 64 83 105 127 147 170 190 212 233]
bb = [21 40 63 82 104 126 146 169 189 211 232 252]
V = rand(252,1); % some sample data
selV = arrayfun(#(t) V(aa(t):bb(t)), 1:12,'uniformoutput',false);
result = cellfun(#yourfunction,selV)
% or
result = cellfun(#(selVi) yourfunction(selVi), selV);
If the function you want to apply has scalar output to every vector input, this should give you an 1x12 array. If the function gives vector output, you'll have to include the uniformoutput parameter:
result = cellfun(#(selVi) yourfunction(selVi), selV,'uniformoutput',false);
which gives you a 1x12 cell array.
If you want to run this in a highly condensed form, you can write (in two lines, for clarity)
aa = [1 22 41 64 83 105 127 147 170 190 212 233]
bb = [21 40 63 82 104 126 146 169 189 211 232 252]
V = rand(252,1); % some sample data borrowed from #Gunther
%# create an anonymous function that accepts start/end of range as input
myFunctionHandle = #(low,high)someFunction(V(low:high));
%# calculate result
%# if "someFunction" returns a scalar, you can drop the 'Uni',false part
%# from arrayfun
result = arrayfun(myFunctionHandle(low,high),aa,bb,'uni',false)
Note that this may run more slowly than an explicit loop at the moment, but arrayfun is likely to be multithreaded in a future release.