SameedSohail92
SameedSohail92

Reputation: 41

Slow speed of UDP reception in 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

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

Upvotes: 2

Views: 4235

Answers (2)

Yvon
Yvon

Reputation: 2993

Let me summarize my comments.

Low code efficiency

  1. 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.

  2. 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.

Upvotes: 0

m_power
m_power

Reputation: 3204

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;

Upvotes: 1

Related Questions