【问题标题】:Vectorize loop with nested if-clause带有嵌套 if 子句的向量化循环
【发布时间】:2016-07-01 09:53:16
【问题描述】:

问题

我正在尝试优化我的代码的运行时,并且在此之前提出了一个类似的问题,其中包括几个嵌套的 if 语句。 Vectorizing nested if-statements

由于我在那里发布的希望能实现一些想法的代码有点长,而且我仍在为嵌套循环的矢量化实现而苦苦挣扎,我想用一些更简单的代码再次询问:

代码

NB_list_all=zeros(length(BML),4);
for NB=1:length(BML);
    NB_list=zeros(4,1);
    %in +x direction
    if isempty(find(BML(:,2)==BML(NB,2)+x_blockdimension & BML(:,3)==BML(NB,3), 1));
        NB_list(1,1)=0;
    else
        NB_list(1,1)=find(BML(:,2)==(BML(NB,2)+x_blockdimension)& BML(:,3)==BML(NB,3));

    end
NB_list_z(NB,:)=NB_list;
end

% BML(:,2) stores the x-coordinate
% BML(:,3) stores the y-coordinate

一些示例数据

BML=
    1 1005  115
    2 1100  115
    3 1419  120
    4 1424  120
    5 660   115
    6 655   115

注意 BML 的大小为 170 000 x 7。

代码说明

我正在尝试使用此代码在我的点云中找到“x_blockdimension”之外的下一个点。如果什么都找不到,则将条目设置为零。现在,由于这需要大量时间来处理 1800 万个点(而且我不只是在寻找一个方向),因此我正在寻找一种通过使用矢量化或逻辑索引来优化它的方法。如果有其他方法可以改进运行时,我会很乐意提供任何提示。

我尝试了什么

if isempty(find(BML(:,2)==BML(:,2)+x_blockdimension & BML(:,3)==BML(:,3), 1));
    NB_list(1,1)=0;
else
    NB_list(1,1)=find(BML(:,2)==(BML(:,2)+x_blockdimension)& BML(:,3)==BML(:,3));

end

但它并没有真正做到我想要它做的事情。

希望能帮到你!

【问题讨论】:

    标签: performance matlab vectorization


    【解决方案1】:

    如果我正确理解了输入的格式,您可以使用带有bsxfun 的广播来获得像这样的矢量化解决方案 -

    % Perform broadcasted comparison corresponding to the iterative comparison
    % in original code to get a boolean array/mask. 
    % Get the row, col indices for the mask, which will correspond to the index
    % values and positions where those values are to be stored in the output. 
    [R,C] = find(bsxfun(@eq,BML(:,2),BML(:,2).'+x_blockdimension) & ...
                                         bsxfun(@eq,BML(:,3),BML(:,3).'));
    
    % Setup output array and store the indices at respcetive positions. 
    NB_list_z_out = zeros(size(BML,1),numel(NB_list));
    NB_list_z_out(C,1) = R;
    

    请注意,输出似乎只是编辑输出数组中的第一列元素,因此在最后一步使用NB_list_z_out(C,1) 进行索引。


    可以建议另一种方法,重点关注内存效率和额外的性能,并获得RC,稍后可以使用它们,就像在前面列出的方法中使用它们一样。实现看起来像这样 -

    % Filter out with "bsxfun(@eq,BML(:,3),BML(:,3).'))".
    [~,~,idx] = unique(BML(:,3),'stable');
    vidx = find(ismember(idx,find(accumarray(idx(:),1)>1)));
    
    % Filter out on remaining ones with valid indices (vidx)
    [R1,C1] = find(bsxfun(@eq,BML(vidx,2),BML(vidx,2).'+x_blockdimension));
    R = vidx(R1);
    C = vidx(C1);
    

    【讨论】:

    • 感谢您的回答...我尝试实现它,但出现以下错误:“使用 bsxfun 时出错内存不足。键入 HELP MEMORY 作为您的选项。 test_neighbours 中的错误(第 3 行) bsxfun(@eq,BML(:,3),BML(:,3).'));'
    • @KiW BML你的实际情况是多少?
    • @ Divakar 大约 170 000x7,我想为 500 000 x 7 的类似进程实现它,第一种情况我需要运行 4 次(在 +x -x +y -y 方向)
    • @ Divakar:如果有帮助,我知道 BML 中的每个元素只存在一个(或没有)值,它满足 +x_blockdimension 的条件,我需要找到它的索引。
    • 我尝试使用您的实现,我编辑了带有问题的问题。我不确定我能 100% 地得到你的代码的作用,所以我想知道是否有办法以所需的方式使用它。不过还是非常感谢
    【解决方案2】:

    如果您知道 BML 中的每一行只有 0 或 1 个匹配项,那么您可以对它们进行排序并使用 diff,而不是使用循环:

    %%  Find matches for x dimension
    
    % sort on x dimension using sortrows, then split the matrix again
    BMLx= sortrows(BML(:,[2:end,1]));
    sorted_xx = BMLx(:,1:end-1);
    idx = BMLx(:,end);
    
    diff_ = diff(sorted_xx);
    x_diff_match = find(diff_(:,1)==x_blockdimension & (diff_(:,2:end)==0));
    % or you might want to use abs(a-b)<told
    
    % assign all zeros as default
    NB_list_x=zeros(length(BML),1);
    % alocate matches
    NB_list_x(idx(x_diff_match)) = idx(x_diff_match+1)
    

    【讨论】:

    • 嘿,谢谢你的回答。我知道 x+x 维度只有一个值具有相同的 y 值,总共有更多的值可以满足条件。如果我查看您的代码,它似乎并不协调,还是我看得太慢了?
    • 抱歉,误解了这个问题。现在检查其他差异(other_dimesions==0)
    • 我尝试实施您的解决方案,这看起来是个好主意,尤其是对于大数据集,但我只是得到零作为邻居。老实说,我不知道为什么......如果你有时间我在这里上传了数据集:s000.tinyupload.com/?file_id=05161766586627414815 ...可能更容易看到结果。我猜你的意思是'(diff_(:,2)== 0)',否则矩阵尺寸不同意。但是,如果您知道为什么结果只是零,我会很高兴:/ 感谢您的帮助!
    • 如果你有一个解决方案会很高兴,因为你的方式似乎快了很多,我只是无法弄清楚问题......
    • 嗨 KiW,我刚刚快速浏览了您的 tinyupload 文件。问题可能是 tinyupload 文件的第一列包含大整数,而您帖子中的示例有 1:end。如果这些是其他一些索引数字,用 1:length(BML) 替换它们会起作用吗?否则,如果第一列实际上是 x 值,则 cat 在第一列之前的 1:n 向量上。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 2012-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多