【问题标题】:Simplifying for loop (matlab)简化for循环(matlab)
【发布时间】:2012-06-11 21:59:34
【问题描述】:

我正在开发一个程序,以计算飞机在目标区域上空飞行时可以看到的内容。当它越过该区域时,它可以跟随许多轨道之一,正常区域大小约为 100。我创建了一个大循环来查看飞机是否可以看到该区域的某些部分,但它的运行效率非常低。我已将该区域定义为网格 1001x1001

xgrid 定义 x 值的 1001x1 变量。

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

这两行之间是可见区域。如果可以看到,则将 seenarea(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 分析器在我的程序的瓶颈处确定了这一点。任何帮助将非常感激。 谢谢,丰富

【问题讨论】:

    标签: matlab loops for-loop vectorization


    【解决方案1】:

    我不能确切地告诉你你想要做什么,但我建议作为第一步用逻辑索引替换内部循环。

    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
    

    【讨论】:

    • 有一个小错误:您定义变量idx 用于逻辑寻址,但之后您使用不存在的变量index 来寻址seenarea
    • ... 另一个 +1 表示耐心 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 2018-04-11
    • 2016-03-06
    • 2020-10-19
    • 1970-01-01
    • 2016-11-20
    相关资源
    最近更新 更多