在 MATLAB 中采用早期救助

Employ early bail-out in MATLAB

本书中有一个 Employ early bail-out 的例子 (http://www.amazon.com/Accelerating-MATLAB-Performance-speed-programs/dp/1482211297) (@YairAltman)。为了提高速度,我们可以转换此代码:

data = [];
newData = [];
outerIdx = 1;
while outerIdx <= 20
    outerIdx = outerIdx + 1;
    for innerIdx = -100 : 100
        if innerIdx == 0
            continue % skips to next innerIdx (=1)
        elseif outerIdx > 15
            break % skips to next outerIdx
        else
            data(end+1) = outerIdx/innerIdx;
            newData(end+1) = process(data);
        end
    end % for innerIdx
end % while outerIdx

此代码:

function bailableProcessing()
for outerIdx = 1 : 5
    middleIdx = 10
    while middleIdx <= 20
        middleIdx = middleIdx + 1;
        for innerIdx = -100 : 100
            data = outerIdx/innerIdx + middleIdx;
            if data == SOME_VALUE
                return
            else
                process(data);
            end
        end % for innerIdx
    end % while middleIdx
end % for outerIdx
end % bailableProcessing()

我们是如何进行这种转换的?为什么我们在新代码中有不同的 middleIdx 范围?在哪里检查新代码中的 innerIdxouterIdx?这个新的 data = outerIdx/innerIdx + middleIdx 计算是什么?

我们只有第二个代码的信息:

We could place the code segment that should be bailed-out within a dedicated function and return from the function when the bail-out condition occurs.

一切远比你想象的简单!

How we did this conversion?

不合理。这两个代码完全不同

Why we have different middleIdx range in new code?

随机性。作者的观点是不同的。

Where is checking for innerIdx and outerIdx in new code?

不需要那个,因为它不是相同的代码。

what is this new data = outerIdx/innerIdx + middleIdx calculation?

一个随机计算以及data(end+1) = outerIdx/innerIdx;原代码

我想作者想要更深刻地说明一些事情:如果你将执行(可能很多)循环(fors/whiles,无关紧要)的代码包装在 函数 并发出 return 语句,如果你以某种方式检测到你已经完成,它将导致有效的 "bailable" 计算,例如比正常情况更早 returns 完成工作的方法。此处通过检查 data == SOME_VALUE 的条件说明了这一点;你可以在那里设置你最喜欢的救助条件:-)

此外,第一个示例中的关键字 [continue/break] 旨在说明您可以 [跳过其余部分 of/leave] 从任何位置开始的最内层循环你打电话给他们。原则上,您可以通过例如

使用这些实施救助
bailing = false;
for outer = 1:1000
   for inner = 1:1000
      if <somebailingcondition>
         bailing = true;
         break;
      else
         <do stuff>
      end
   end
   if bailing
     break;
   end
end

但这将非常笨拙,因为 "cascade" 的中断将需要只要你有嵌套循环并弄乱代码。

我希望这可以澄清你的问题。

很抱歉,我没有在文中说明第二个代码段不是第一个代码段的直接替换。如果您重读早期的 bail-out 部分 (3.1.3),您可能会发现它有两个主要部分:

本节的第一部分(包括最上面的代码段)说明了使用break/continue的基本机制以便bail-out脱离复杂的处理循环,以节省处理时间在计算不需要的值时。

相比之下,本节的第二部分处理的是我们希望跳出不是直接父循环的祖先循环的情况。我在文中提到,在这种情况下我们可以使用三种替代方案,您提到的第二个代码段就是其中之一(其他替代方案是使用带有 break/continue 的专用标志并使用 try/catch块)。我在本节的第二部分提供的三个代码段应该彼此等效,但它们不等效于本节顶部的 code-segment。

也许我应该在课文中澄清这一点,或者我应该在整个过程中使用相同的例子。我会在本书的第二版中考虑这一点(如果它出现的话)。

我在本书的其他部分使用了这些代码段的变体来说明性能加速的其他各个方面(例如,3.1.4 和 3.1.6)——在所有这些情况下,代码段都不是彼此等价。它们仅用于说明相应的文本。

希望您总体上喜欢我的书并认为它很有用。如果您能在亚马逊上对此给予积极反馈,我将不胜感激 (direct link)。

p.s。 - @SamRoberts 正确地推测提及我的名字会起到 "bat-signal" 的作用,引起我的注意:-)