简化循环(matlab)

时间:2012-06-11 21:59:34

标签: matlab loops for-loop vectorization

我正在制定一项计划,计算一架飞机飞过目标区域时可以看到的情况。当它越过该区域时,它可以跟随许多轨道中的一个,大约100个正常区域大小。我已经创建了一个大型循环,以查看该平面是否可以看到该区域的某些部分但是它的运行效率非常低。我已将该区域定义为网格1001x1001

xgrid定义x值的变量1001x1。

thelines是一个可变的2 x 1001 x轨道,其中第一行是顶行相应x值的y值。第二行是底线的y值。

这两条线之间是可见区域。如果可以看到它将seearea(1001x1001)上的点标记为1.如果不是它的0.

for M=1:tracks
    for f=1:1001
        for i=1:1001
            if xgrid(f,1)>thelines(i,1,M) && xgrid(f,1)<thelines(i,2,M);
                seenarea(f,i,M)=1; % This indicated the area has been seen
            else
                seenarea(f,i,M)=0; % This is not seen
            end
        end
    end
    fullbestinfo(1,M)={seenarea(:,:,M)}; % This stores the seen area in another cell
    if max(seenarea(:,:,M)) < 1 % No area seen, stop
        seenarea(:,:,M)=[];
        break
    end
end

我已经使用matlab探查器确定了我的程序的瓶颈。任何帮助将非常感激。 谢谢,Rich

1 个答案:

答案 0 :(得分:7)

我无法确切地说出你想要做什么,但我建议第一步用逻辑索引替换内部循环。

seenarea = false(1001, 1001, tracks); #% preallocate matrix to 'false'
xgrid = repmat(1:1001, 1001, 1); #%same size as the first 2D of seenarea

for M=1:tracks
    border1 = thelines(:,ones(1,1001),M); #% same size as xgrid
    border2 = thelines(:,ones(1,1001)*2,M); #% same size as xgrid
    idx = xgrid > border1 & xgrid < border2; #% idx is a "logical index" 
             #%           ^--- single ampersand
    seenarea(idx,M)=true; 
end

使用逻辑索引,您可以使用单个操作替换嵌套循环的百万次迭代。

这是另一个提示:使用逻辑矩阵而不是双矩阵来存储真/假值。

>>m1 = zeros(1001,1001,100);
>> m2 = false(1001,1001,100);
>> whos m1
  Name         Size                      Bytes  Class     Attributes

  m1        1001x1001x100            801600800  double              

>> whos m2
  Name         Size                      Bytes  Class      Attributes

  m2        1001x1001x100            100200100  logical 

如您所见,逻辑矩阵的内存使用率低了8倍。

速度测试:我很好奇这会产生多大的差异。下面是一个快速测试(好吧,仅适用于其中一个实现)。对内环进行矢量化导致我的机器上的速度大大增加<75倍 - ,将10个音轨的时间从7秒减少到大约0.1秒。

tic;
for rep=1:100
    for M=1:tracks
        for f=1:1001
            for i=1:1001
                if xgrid(f,1)>thelines(i,1,M) && xgrid(f,1)<thelines(i,2,M);
                    seenarea(f,i,M)=1; 
                else
                    seenarea(f,i,M)=0; 
                end
            end
        end
    end
end
disp(toc/100)
    7.3459

tic;
for rep=1:100
    for M=1:tracks
        border1 = thelines(:,ones(1,1001),M); 
        border2 = thelines(:,ones(1,1001)*2,M); 
        idx = xgrid > border1 & xgrid < border2;                     
        seenarea(idx,M)=true; 
    end
end
disp(toc/100)
    0.0964

>> 7.3459/.0964    
ans =    
   76.2023