【问题标题】:How can i make this code more time efficient?我怎样才能让这段代码更省时?
【发布时间】:2012-10-12 08:24:29
【问题描述】:

这是 Profiler 报告的一部分,显示了这些行如何占用时间。可以改进吗?

         434 %clean up empty cells in subPoly
         228  435 if ~isempty(subPoly) 
         169  436     subPoly(cellfun(@isempty,subPoly)) = []; 
              437 
              438     %remove determined subpoly points from the hull polygon
         169  439     removeIndex = zeros(size(extendedPoly,1),1); 
         169  440     for i=1:length(subPoly) 
         376  441         for j=1:size(subPoly{i}(:,1)) 
       20515  442             for k=1:size(extendedPoly,1) 
6.12 5644644  443                 if extendedPoly(k,:)==subPoly{i}(j,:) 
       30647  444                     removeIndex(k,1)=1; 
       30647  445                 end 
1.08 5644644  446             end 
0.02   20515  447         end 
         376  448     end 
         169  449     extendedPoly = extendedPoly(~removeIndex(:,1),:);  
         169  450 end 

【问题讨论】:

  • 你能解释一下这段代码的作用吗?
  • 根据是否可能匹配,您可能会通过重新排序循环以使 k 在外部获得很大的收益。然后,对于任何 i/j 与 k 的第一次匹配,您可以设置 removeIndex,然后突破 i/j 的其余部分(提前退出)。
  • 嗯。矢量== 在这种情况下很奇怪。你的意思是整行必须在数字上相等吗?然后使用all(somerow == someotherrow) 明确说明。还要注意与浮点表示相关的舍入问题。考虑一些带有阈值的距离度量。

标签: performance matlab time for-loop


【解决方案1】:

由于Matlab倾向于认为命令行中的所有内容都是双精度数组,并且假设您的数组和单元格数组的内容是数字,您可以替换

         if extendedPoly(k,:)==subPoly{i}(j,:) 
             removeIndex(k,1)=1; 
         end 

与等价物

removeIndex(k,1) = extendedPoly(k,:)==subPoly{i}(j,:)

这可能会节省几纳秒,但如果节省更多,我会有点惊讶。

我怀疑如果我更聪明或更勤奋,我可能会用一个单一的赋值替换你的整个循环嵌套

removeIndex = extendedPoly==subPoly

这里的诀窍是确保表达式中的所有数组都具有相同的维度。

【讨论】:

  • removeIndex(k,1)=1;,但是你写的复制了extendedPoly和subpoly的值,只要它们相等..而不是我希望它是1。
【解决方案2】:

您可能正在接近当前嵌套策略的性能限制。 “慢”行每次执行只需要 1 微秒。

通常在这样的集合匹配情况下,最好对两个集合进行排序,然后同时对两个集合执行一个循环。 (谷歌“插入排序”了解更多信息,另请参阅此相关问题/答案Optimization of timestamp filter in MATLAB - Working with very large datasets

目前尚不清楚如何最好地将其应用于您的情况。如果您发布一个可执行示例,我们可以更仔细地研究一下。

在不查看可执行代码的情况下,将向量的 subPoly 单元格扩展为单个排序的数字数组(称为 sortedElementsToremove 之类的东西)可能是有意义的。然后从extendedPoly 获取排序顺序,如下所示:[~, ixsSortExpended] = sort(extendedPoly);

现在您可以使用带有两个索引的单个循环来执行屏蔽。像这样的东西(代码未经测试):

ixExtended = 1;  %Index though sort order
for ixSub = 1:length(sortedElementsToremove);
    %Use while to update second index
    while ...
            (extendedPoly(ixsSortExpended(ixExtended))  < sortedElementsToremove(ixSub) ) && ...
            ixExtended < length(ixsSortExpended)
        ixExtended = ixExtended + 1;
    end
    if (sortedElementsToremove(ixSub) == extendedPoly(ixsSortExpended(ixExtended)))
        removeIndex(ixsSortExpended(ixExtended)) = true;
    end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 2017-08-15
    • 1970-01-01
    • 2013-05-21
    相关资源
    最近更新 更多