简体   繁体   English

使用嵌套的if子句进行Vectorize循环

[英]Vectorize loop with nested if-clause

Problem 问题

I am trying to optimize the runtime of my code and have asked a similar question before that included several nested if-statements. 我正在尝试优化我的代码的运行时,并在包含几个嵌套的if语句之前询问了类似的问题。 Vectorizing nested if-statements 矢量化嵌套的if语句

As the code I posted there hoping for some ideas I might implement was a bit long and I am still struggeling with the implementation of vectorization for nested loops I would like to ask again with some easier code: 正如我在那里发布的代码希望我可能实现的一些想法有点长,我仍然在讨论嵌套循环的矢量化的实现,我想再问一些更简单的代码:

Code

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

Some example data 一些示例数据

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

Notice BML has a size of 170 000 x 7. 注意BML的大小为170 000 x 7。

Code Description 代码说明

What I am trying with this code is finding the next point in my point cloud which is "x_blockdimension" away. 我正在尝试使用此代码的是找到我的点云中的下一个点,即“x_blockdimension”。 If nothing can be found the entry is set to zero. 如果找不到任何内容,则条目设置为零。 Now as this takes a huge amount of time for 18 Million points (and I am not just looking in one direction) I am looking for a way to optimize this by either using vectorization or logical indexing. 现在因为这需要花费大量时间来获得1800万个点(而且我不只是朝着一个方向看),我正在寻找一种通过使用矢量化或逻辑索引来优化它的方法。 If there is another way to improve the runtime I would be happy for any tips. 如果有另一种方法来改善运行时间,我会很高兴任何提示。

What I tried 我尝试了什么

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

But it is not really doing what I want it to do. 但它并没有真正做我想做的事情。

I hope for some help! 我希望能得到一些帮助!

If I understood the format of inputs correctly, you can use broadcasting with bsxfun for a vectorized solution like so - 如果我正确理解了输入的格式,你可以使用bsxfun广播来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;

Please note that it seemed that the output is only editing the first column elements in the output array and therefore indexing with NB_list_z_out(C,1) at the last step. 请注意,输出似乎只是编辑输出数组中的第一个列元素,因此在最后一步使用NB_list_z_out(C,1)进行索引。


An alternative approach could be suggested with focus on memory efficiency and additionally performance too and get R and C , which could be used later on just like they were used in the approach listed earlier. 可以建议一种替代方法,重点关注内存效率和性能,并获得RC ,这可以在以后使用,就像它们在前面列出的方法中使用的那样。 The implementation would look something like this - 实现看起来像这样 -

% 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);

If you know that there is only 0 or 1 match for every row in BML, then you can sort them and use diff, rather than using a loop: 如果你知道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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM