在Matlab中UDP接收速度慢

时间:2014-08-11 07:34:01

标签: matlab udp fpga

我的FPGA使用100 mbps以太网在网络上发送UDP数据包,并编写了一个MATLAB代码来捕获数据。问题是我在接收期间在MATLAB中的速度非常低,大约50 kbps。 FPGA套件连接到gbps交换机,然后连接到PC。交换机中没有互联网电缆。 我正在粘贴下面的matlab代码。如果我尝试通过增加缓冲区大小来提高速度,则丢弃数据包。当前设置是通过命中和试验,我成功地收到所有数据。有没有办法提高MATLAB中的数据接收速度?

Code ::(从FPGA到Matlab的UDP)     CLC     清除所有     关闭所有

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;

/////////////////////////////////////////////// //////////

上述代码的修改版本(易于理解)+图像显示问题

还:显示数据变量的图像,缓冲区大小为20个数据包(18个字节/数据包)。数据不能全部为零,如图中所示。它代表丢失的数据包。 ////////////////////////////////////////////////// ///////

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

2 个答案:

答案 0 :(得分:1)

我查看了您的代码并找到了一些基本的更正,让我知道它是否会加快您的代码。

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;

答案 1 :(得分:0)

让我总结一下我的评论。

代码效率低

  1. 正如@m_power所指出的那样,使用ij可以减慢代码的速度。有关详细信息,请参阅this。在Matlab中,您始终使用iijj

  2. 您没有初始化data。了解Mathworks如何解释这一点。如果#1“慢一点”,那么#2会慢下来。

  3. 由于您的代码很慢,因此无法保证每次FPGA发送数据包时,您的PC都能找到任何可用的缓冲区来接收数据包。

    完整缓冲区

    if (count == buffer_size) 
        data(:, i) = a;           %If Read_BYtes(Count) == BufferSize Store in Data
    end
    

    那么如果数据包小于缓冲区data(:,i) = nothing?这是你在第3,4和5栏中获得零的最可能原因。

    空缓冲区

    如果您已完成之前的更改,则第3,4和5列中的零也可能来自空缓冲区。当Matlab读取缓冲区时,不保证缓冲区可以携带一些东西,因此一些for次迭代可以捕获零长度内容data(:,ii) = 0

    使用while循环来解决此问题。仅计入非空缓冲区读数。

    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
    

    ....不完整的数据包?

    你等待一个完整的缓冲区,因为每次你想要读取整个数据包?我突然意识到了;我多么愚蠢!

    但你所做的就是继续读取缓冲区,并且丢弃数据,只要它短于缓冲区长度。

    相反,您需要聚合每个循环中的数据。

    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
    

    测试 - 我将fread更改为随机整数生成器ii,记住缓冲区的读取次数。

    清除所有; 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)
    

    结果是

        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
    

    如您所见,每次fread输出的长度等于或小于缓冲区大小。但是只有完全接收到当前列时,它才跳转到下一列。