开发区域

先进与MATLAB软件开发

绩效考核标准3:尺度的任务

规模还是规模。这是个问题。在谈到算法复杂度时,表示问题的答案通常是非常重要的。不管什么恒定因素影响算法的速度,可怜的扩展性能严重限制的范围问题可以解决。你如何衡量你的代码运行时的复杂性?如果你没有一个好的方法(或即使你!)然后再一次性能测试框架是站在你这边。我是惊讶当我学会了这一点一个奇怪的技巧来衡量算法的复杂性。

(不)秘密就是现在性能测试是测试,性能测试参数化测试!利用这一特性,我们可以发送的大小问题作为参数。让我们来看看这是如何实现的。

内容

的代码

首先,我们需要一些代码规模。让我们看看一个简单的函数,它将使我们能够模拟一些工作:

函数doSomeWork (n)%的简单函数,模拟一些常量时间的工作要做。暂停(n);结束

“工作”这个小函数,我们可以玩一些不同时间复杂度的算法。首先,让我们来看看一些美元\ mathcal {O}(1)美元,或持续时间:

函数constantTimeFunction (~) doSomeWork (2);结束

很容易。注意constantTimeFunction接收一个参数,但简单地忽略它。该参数的大小问题,和这个函数忽略了它,因为常数时间算法无论大小都是相同的。我们如何做一些美元\ mathcal {O} (n),美元或线性吗?把它放在一个for循环的大小问题:

函数linearTimeFunction (n)idx = 1: n doSomeWork (0.001);结束结束

现在不要担心这里的例子常数。他们真的可以是任何东西,我只是调整他们得到一些合理的演示。好吧,继续让我们创建一个美元\ mathcal {O} (n ^ 2)美元二次时间函数通过使用两个for循环的大小:

函数quadraticTimeFunction (n)idx1 = 1: nidx2 = 1: n doSomeWork (0.0001)结束结束结束

我们如何创造出的东西那是美元\ mathcal {O}({} \对数n) $ ?一种方法是简单地减少迭代次数,这样随着问题规模的单位有更少的工作要做。这可能看起来像这样:

函数logTimeFunction (n) doSomeWork (0.001);n > 1 n = n / 2;doSomeWork (0.01)结束结束

现在,终于让我们展示一些美元\ mathcal {O} (2 ^ {n}),美元指数或复杂性。递归是一个很好的随时撤退(!)一个指数的算法。

函数exponentialTimeFunction (n) doSomeWork(1)的军医;idx = 1:圆形(n) exponentialTimeFunction (idx-5);结束结束

好了,现在我们有我们所有的“代码”,让我们看看我们如何评估它的鳞片。你可以很容易地通过创建一个性能测试使用problemSizeTestParameter财产。如果这个属性包含不同的参数数据单元阵列或结构中如果你想给每个点一个意图揭示标签。对于这个测试让我们创建一些点在第一个两年。一旦定义这个参数,它非常简单的通过性能测试方法和得到你的结果:

classdefScalingTest < matlab.perftest.TestCase属性(TestParameter) problemSize = num2cell(圆(logspace (0、2、10)));结束方法(测试)函数problemSize testConstantTime (~) constantTimeFunction (problemSize);结束函数problemSize testLogTime (~) logTimeFunction (problemSize);结束函数problemSize testLinearTime (~) linearTimeFunction (problemSize);结束函数problemSize testQuadraticTime (~) quadraticTimeFunction (problemSize);结束函数testExponentialTime testCase (testCase, problemSize)。assumeLessThan (problemSize, 50);testCase.startMeasuring;exponentialTimeFunction (problemSize);testCase.stopMeasuring;结束结束结束

让我们把我们的数据,看看每个单独的算法。我可以通过调用runperf“名称”选项与一些通配符来缩小每个感兴趣的方法,从不断的算法:

constantResult = runperf (“ScalingTest”,“名字”,“* testConstantTime *”);
运行ScalingTest .......... .......... .......... .......... .......... .......... .......... ..........完成ScalingTest __________

让我们创建一个helper函数在每个尺寸的最小值。这将帮助我们迅速退出数据点。我要选择每个样本的最小,因为它是周二,周二告诉我真的喜欢分钟。

findMins = @ (resultArray) arrayfun (@ min (result.Samples.MeasuredTime)(结果),resultArray);ax =轴;ylabel (“执行时间(s)”);包含(“问题大小”);持有;网格;problemSize = [ScalingTest.problemSize {}):;情节(ax, problemSize findMins (constantResult),“线宽”2);腿=传奇({“美元\ mathcal {O}(1)的美元},“翻译”,“乳胶”);

这看起来到处直到你意识到规模。调整y轴从0开始显示其相当平坦。

ax.YLim (1) = 0;

好的,现在我们可以开始添加更复杂的算法,看看他们如何比较。下一个对数:

logResult = runperf (“ScalingTest”,“名字”,“* testLogTime *”);情节(ax, problemSize findMins (logResult),“线宽”2);轴;腿= ([leg.String传奇“美元\ mathcal {O}({} \对数n)的美元),“翻译”,“乳胶”);
运行ScalingTest .......... .......... .......... .......... .......... .......... .......... .......... ....完成ScalingTest __________

然后线性:

linearResult = runperf (“ScalingTest”,“名字”,“* testLinearTime *”);情节(ax, problemSize findMins (linearResult),“线宽”2);轴;腿= ([leg.String传奇“美元\ mathcal {O} (n)的美元),“翻译”,“乳胶”);
运行ScalingTest .......... .......... .......... .......... .......... .......... .......... .......... ........完成ScalingTest __________

然后二次:

quadraticResult = runperf (“ScalingTest”,“名字”,“* testQuadraticTime *”);情节(ax, problemSize findMins (quadraticResult),“线宽”2);轴;腿= ([leg.String传奇“美元\ mathcal {O} (n ^ 2)美元的),“翻译”,“乳胶”);
运行ScalingTest .......... .......... .......... .......... .......... .......... .......... .......... ..........完成ScalingTest __________

…最后指数。注意,因为指数爆炸如此之快,我们需要限制大小用一个假设的问题。因为我们不想一次假设,我们显式地设置测量边界排除假设调用。对于那些失败的大小的假设,结果有效的属性将是错误的,所以我们可以用它来修剪只有有效的测量我们收集的数据。

exponentialResult = runperf (“ScalingTest”,“名字”,“* testExponentialTime *”);有效= [exponentialResult.Valid];validResult = exponentialResult(有效);validSize = problemSize(有效);情节(ax, validSize findMins (validResult),“线宽”2);腿= ([leg.String传奇“美元\ mathcal {O} (2 ^ n)的美元),“翻译”,“乳胶”);
运行ScalingTest .......... .......... .......... .......... .......... .......... .......... .......... . .= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ScalingTest / testExponentialTime (problemSize = value9)过滤。= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =。= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ScalingTest / testExponentialTime (problemSize = value10)过滤。= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =。完成ScalingTest __________失败总结:名字不完整的原因失败(s) = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ScalingTest / testExponentialTime (problemSize = value9) X过滤的假设。- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ScalingTest / testExponentialTime (problemSize = value10) X过滤的假设。

现在清楚的是,试图看到这在线性范围内越来越荒谬。我们去对数尺度。

斧子。YScale =“日志”;

我们走吧!这是我们所有的仿真算法的规模。正如您可以看到的,算法的复杂性是非常重要的。随着问题规模大小,大的常数因子迅速成为无关紧要。

各部分的总和

然而,仅仅为了好玩让做一些MATLAB有趣发现不变因素。如果你不能提高算法的复杂性,也许你可能想看到不变的因素是为了看到经验方法来提高大小可以实现的问题。在MATLAB可以使用矩阵左除永远美丽。第一次让所有这些代码放入一个函数和数据收集的可伸缩性

函数complexFunction (n) constantTimeFunction (n);logTimeFunction (n);linearTimeFunction (n);quadraticTimeFunction (n);exponentialTimeFunction (n);结束

现在让我们编写测试,收集运行时数据

classdefFullComplexityTest < matlab.perftest.TestCase属性(TestParameter) problemSize = {1、2、3、5、8、13、22};结束方法(测试)函数problemSize testComplexFunction (~) complexFunction (problemSize);结束结束结束
additiveResult = runperf (“FullComplexityTest”);problemSize = [FullComplexityTest.problemSize {}):;executionTime = findMins (additiveResult);%从一个新鲜的轴开始删除(ax) ax =轴;ylabel (“执行时间(s)”);包含(“问题大小”);持有;网格;情节(ax, problemSize, executionTime“o”);
运行FullComplexityTest .......... .......... .......... .......... ..........……完成FullComplexityTest __________

它适合吗?

现在让我们适应数据!注意,$ y = k_0 + k_1 \ log {} n + k_2n + k_3n ^ 2 + k_42 ^ n美元

格式n = problemSize。”;y = executionTime。';X =[(大小(n)), log (n), n, n。^ 2,2 . ^ n];X、y k = N = (0:0.1:22)”;Y =[(大小(N)), log (N), N, N。^ 2,2。^ N] * k;情节(ax, N Y“- - -”,“线宽”2);
k = 0.203249252542941 0.024019014853585 -0.000703911764008 0.000243945808296 0.000000018436312

…我们走。找好。

你认为,你看到自己分析MATLAB代码天平使用这种技术如何?




发表与MATLAB®R2016a

|
  • 打印
  • 发送电子邮件

评论

留下你的评论,请点击在这里MathWorks账户登录或创建一个新的。