MATLAB:以尽可能最快的方式从另一个大矢量中的每个元素中减去大矢量中的每个元素

时间:2014-03-27 14:37:08

标签: matlab vector

这是我的代码,它不是简单的减法。我们想要在一个边界tmin和tmax内从另一个矢量中的每个值中减去一个矢量中的每个值。 time_a和time_b是具有时间的非常长的向量(以ps为单位)。 binsize仅用于绘制类似范围内的绘图时间。最长的方法是循环遍历每个元素并减去另一个向量中的每个元素,但这将需要永远,我们正在谈论具有数百兆字节到gb的向量。

function [c, dt, dtEdges] = coincidence4(time_a,time_b,tmin,tmax,binsize)
% round tmin, tmax to a intiger multiple of binsize:
if mod(tmin,binsize)~=0
    tmin=tmin-mod(tmin,binsize)+binsize;
end
if mod(tmax,binsize)~=0
    tmax=tmax-mod(tmax,binsize);
end

dt = tmin:binsize:tmax;
dtEdges = [dt(1)-binsize/2,dt+binsize/2];
% dtEdges = linspace((tmin-binsize/2),(tmax+binsize/2),length(dt));
c = zeros(1,length(dt));

Na = length(time_a);
Nb = length(time_b);

tic1=tic;
% tic2=tic1;
% bbMax=Nb;
bbMin=1;
for aa = 1:Na
    ta = time_a(aa);
    bb = bbMin;
    %    tic
    while (bb<=Nb)
        tb = time_b(bb);
        d = tb - ta;
        if d < tmin
            bbMin = bb;
            bb = bb+1;
        elseif d > tmax
            bb = Nb+1;
        else
%             tic
%             [dum, dum2] = histc(d,dtEdges);
            index = floor((d-dtEdges(1))/(dtEdges(end)-dtEdges(1))*(length(dtEdges)-1)+1);

%             toc
            %            dt(dum2)
            c(index)=c(index)+1;
            bb = bb+1;
        end
    end
%     if mod(aa, 200) == 0
%         toc(tic2)
%         tic2=tic;
%     end
end
% c=c(1:end-1);
toc(tic1)
end

1 个答案:

答案 0 :(得分:0)

嗯,这不是最终答案,而是一些简化和加速系统的线索:

首先,使用缓存值。例如,在您的行中:

  

index = floor((d-dtEdges(1))/ (dtEdges(end)-dtEdges(1))*(length(dtEdges)-1) +1);

你的循环每次重复都会重复相同的计算。您可以在开始循环之前计算该值,缓存它然后重用存储的结果:

  

cached_dt_constant =(dtEdges(end)-dtEdges(1))*(length(dtEdges)-1);

然后在循环中使用:

  

index = floor((d-dtEdges(1))/ cached_dt_constant +1);

如果你有这么多的循环迭代,你将以这种方式节省宝贵的时间。

其次,我不完全确定计算的目的是什么,但是你可以通过使用matlab的索引功能来节省时间。通过像这样替换代码的下半部分,我的执行时间会快2到3倍(显然也会产生相同的结果)。

Na = length(time_a);
Nb = length(time_b);

tic1=tic;
dtEdge_span = (dtEdges(end)-dtEdges(1)) ;
cached_dt_constant = dtEdge_span * (length(dtEdges)-1) ;

for aa = 1:Na
    ta = time_a(aa);

    d = time_b - ta ;
    iok = (d>=tmin) & (d<=tmax) ;
    index = floor( (d(iok)-dtEdges(1)) ./ cached_dt_constant +1 ) ;
    c(index) = c(index) +1 ;

end
toc(tic1)
end

现在只有一个循环可以通过,内部循环已被移除并被矢量化计算所取代。通过进一步刮擦头部,即使没有顶部循环也可能有一种方法可以做,并且仅使用矢量化计算。虽然这需要有足够的内存来一次处理相当大的数组 如果每个值的精度并不重要(我经常看到你的圆形和底部值),请尝试将初始向量转换为“单个”值。键入而不是默认的matlab&#39; double&#39;。这几乎会使你的记忆能够一次性处理的数组大小翻倍。