这里有一些关于如何在MATLAB中创建循环缓冲区的好帖子(例如this one)。然而,通过查看它们,我不相信它们适合我的应用程序,因为我所寻求的是MATLAB中的循环缓冲解决方案,它不涉及任何旧数据的复制。
使用一个简单的例子,让我们说我一次处理50个样本,每次迭代我读取10个样本。我将首先完成5次迭代,填充我的缓冲区,最后处理我的50个样本。所以我的缓冲区将是
[B1 B2 B3 B4 B5]
,其中每个'B'是10个样本的块。
现在,我读了接下来的10个样本,称之为B6。我希望我的缓冲区现在看起来像:
[B2 B3 B4 B5 B6]
问题就是这个 - 我不想每次复制旧数据,B2,B3,B4,B5,因为它在时间上变得昂贵。 (我有非常大的数据集)。
我想知道是否有办法在不复制“旧”数据的情况下执行此操作。谢谢。
答案 0 :(得分:5)
快速实现循环缓冲区的一种方法是使用模数绕回到前面。这将稍微修改您指定的数据的顺序,但如果您只是用最新的数据替换最旧的数据而不是
,则可能更快且等效[B2 B3 B4 B5 B6]
你得到了
[B6 B2 B3 B4 B5]
使用这样的代码:
bufferSize = 5;
data = nan(bufferSize,1)';
for ind = 1:bufferSize+2
data(mod(ind-1, bufferSize)+1) = ind
end
这适用于任意大小的数据。
如果您不熟悉模数,mod
函数会有效地返回除法运算的剩余部分。因此mod(3,5)
会返回3
,mod(6,5)
会返回1
,mod(7,5)
会返回2
,依此类推,直到您达到等于0的mod(10,5)
为止再次。这允许我们通过在每次到达结束时回到起点来“环绕”向量。代码中的+1
和-1
是因为MATLAB将矢量索引设置为1而不是0,因此为了使数学计算正确,您必须在执行mod
之前删除1将其添加回来以获得正确的索引。结果是当你尝试将第6个元素写入向量时,将其写入向量中的第1个位置。
答案 1 :(得分:1)
我的想法是使用一个包含5个条目的单元格数组,并使用一个变量来索引应该在下一步中覆盖的子数组。例如。
之类的东西 a = {ones(10),2*ones(10),3*ones(10),4*ones(10),5*ones(10)};
index = 1;
在下一步中,您可以写入子数组:
a{index} = 6*ones(10);
并像
一样增加索引index = index+1
显然,某种限制:
if(index > 5) % FIXED TYPO!!
index = 1;
end
那会是给你的吗?
编辑:要看的另一件事是条目的分类,因此总是会被某些条目转移,但取决于您如何继续使用数据,您可以例如根据变量index
移动数据的使用。
EDIT2 :我有另一个想法:在MATLAB中使用类怎么样?您可以使用句柄类来保存数据,因此使用缓冲区仅引用数据。这个可能使它更快一些,具体取决于您拥有的数据(数据集的大小等)以及您在代码中将有多少班次。参见例如在这里:Matlab -- handle objects
您可以使用简单的句柄类:
classdef Foo < handle
properties (SetAccess = public, GetAccess = public)
x
end
methods
function obj = foo(x)
% constructor
obj.x = x;
end
end
end
将数据存储在其中:
data = [1 2 3 4];
foo = Foo(data); % handle object
然后只将对象引用存储在循环缓冲区中。在发布的链接中,答案显示作业bar = foo
不会复制对象,但实际上只保留了引用:
foo.x = [3 4]
disp(bar.x) % would be [3 4]
但如上所述,由于OOP开销,我不知道这是否会更快。这可能取决于您的数据......以及有关它的更多信息:http://www.matlabtips.com/how-to-point-at-in-matlab/
答案 2 :(得分:0)
我刚上传了我的解决方案,用于快速循环缓冲区,不会复制旧数据
http://www.mathworks.com/matlabcentral/fileexchange/47025-circvbuf-m
这种循环缓冲区的主要思想是持续快速的性能 在程序中使用缓冲区时避免复制操作:
% create a circular vector buffer
bufferSz = 1000;
vectorLen= 7;
cvbuf = circVBuf(int64(bufferSz),int64(vectorLen));
% fill buffer with 99 vectors
vecs = zeros(99,vectorLen,'double');
cvbuf.append(vecs);
% loop over lastly appended vectors of the circVBuf:
new = cvbuf.new;
lst = cvbuf.lst;
for ix=new:lst
vec(:) = cvbuf.raw(:,ix);
end
% or direct array operation on lastly appended vectors in the buffer (no copy => fast)
new = cvbuf.new;
lst = cvbuf.lst;
mean = mean(cvbuf.raw(3:7,new:lst));
检查截图,看看如果缓冲区很大,这个循环缓冲区有优势,但每次附加的数据大小很小,因为circVBuf的性能不依赖于缓冲区大小,与简单的副本相比缓冲液中。
双缓冲可以根据要在任何情况下附加的数据来确定追加的预测时间。将来这个课程会给你一个双重缓冲的选择是或否 - 如果你不需要保证时间,事情就会加速。