问题
我正在尝试优化代码的运行时,并在包含多个嵌套的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
但它并没有真正按照我的意愿去做。
我希望得到一些帮助!
答案 0 :(得分: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)
进行索引。
可以建议一种替代方法,重点关注内存效率和性能,并获得R
和C
,这可以在以后使用,就像它们在前面列出的方法中使用的那样。实现看起来像这样 -
% 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);
答案 1 :(得分:1)
如果您知道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)