估计实现的实际(非理论)运行时复杂性

时间:2013-07-05 16:52:28

标签: java complexity-theory benchmarking caliper microbenchmark

计算机科学领域的任何人都知道HeapSort在理论上是O(n log n)最坏的情况,而QuickSort最差的情况是O(n^2)。但是,实际上,一个实现良好的QuickSort(具有良好的启发式)将在每个数据集上优于HeapSort。一方面,我们几乎没有观察到最坏的情况,另一方面,例如CPU缓存行,预取等在许多简单的任务中产生巨大的差异。而且例如QuickSort可以在O(n)中处理预分类数据(具有良好的启发式),HeapSort将始终重新组织O(n log n)中的数据,因为它不利用现有结构。

对于我的玩具项目caliper-analyze,我最近一直在研究从基准测试结果中估算算法的实际平均复杂度的方法。特别是,我用不同的多项式尝试了Lawson和Hanson的NNLS拟合。

但是,它还不能很好地工作。有时候我会得到有用的结果,有时我却没有。我认为只做更大的基准可能会有所帮助,特别是尝试更多的参数。

以下结果用于以具有10%随机性的SAW模式对Double对象进行排序。对于此次运行,n最多只能达到500,因此对于实际使用来说它并不具有代表性......数字是估计的运行时对大小的依赖性。输出手动编辑并手动排序,因此反映工具当前提供的内容!

BubbleSortTextbook       LINEAR: 67.59  NLOG2N:  1.89  QUADRATIC: 2.51
BubbleSort               LINEAR: 54.84                 QUADRATIC: 1.68
BidirectionalBubbleSort  LINEAR: 52.20                 QUADRATIC: 1.36
InsertionSort            LINEAR: 17.13  NLOG2N:  2.97  QUADRATIC: 0.86
QuickSortTextbook                       NLOG2N: 18.15
QuickSortBo3             LINEAR: 59.74                 QUADRATIC: 0.12
Java                     LINEAR:  6.81  NLOG2N: 12.33
DualPivotQuickSortBo5                   NLOG2N: 11.28
QuickSortBo5             LINEAR:  3.35  NLOG2N:  9.67

你可以看出,虽然在这个特定的设置中(通常它完全没有令人满意)但结果在很大程度上与已知的行为一致:冒泡排序确实很昂贵,并且QuickSort上的良好启发式方法要好得多。但是,例如例如,具有三个中值启发式的QuickSort最终得出O(n + n^2)估计,而其他QuickSort估计为O(n + n log n)

现在问我的实际问题:

  • 您是否知道从基准数据执行运行时复杂性分析的算法/方法/工具,以便预测哪个实现(如您所见,我对比较相同算法!)在真实数据上表现最佳?
  • 您是否了解与此相关的科学文章(估算实施的平均复杂程度)?
  • 您是否知道有效的拟合方法,有助于在此获得更准确的估算值?例如。 NNLS的正规化版本。
  • 您是否知道需要多少样本来获得合理估算的经验法则? (特别是,工具什么时候不应该给出任何估计,因为它可能会不准确?)

让我再次强调,我对理论复杂性或正式分析不感兴趣。我有兴趣了解实现(理论上甚至相同的算法)如何对真实CPU上的基准数据执行... 对于我来说,共同范围的数值因素是我的主要关注点,更多而不是渐近行为。 (不,从长远来看,它不仅仅是时间复杂性和排序。但我对索引结构和其他参数感兴趣。如果我没有弄错的话,卡尺也可以测量内存消耗)另外,我是在 java 中工作。一个只调用Matlab内置的方法对我来说毫无用处,因为我不是生活在matlab世界中。

如果我有时间,我会尝试重新运行一些具有更多种类的基准测试,因此我获得了更多的数据点。也许它会起作用......但我相信有更强大的回归方法可以用来获得更好的估算,即使是从较小的数据集。另外,我想检测样品何时太小而无法进行任何预测!

1 个答案:

答案 0 :(得分:2)

如果你想要实际的复杂性,你最好测量它。试图猜测程序如何在不进行测量的情况下执行是非常不可靠的。

同一程序在不同的机器上的执行方式可能大不相同。例如一个算法可能在一台机器上更快,但在另一台机器上更慢。

你的程序可能会变慢,这取决于机器正在做什么,所以一个看起来不错但很多地使用缓存等资源的算法可能会变慢,并且当它必须共享这些资源时会使其他程序变慢。

在机器上单独测试算法的速度比在实际程序中使用算法快2-5倍。

  

您是否知道获得合理估算所需的样本数量的经验法则? (特别是,工具什么时候不应该给出任何估计,因为它可能不准确?)

为了确定90%或99%的百分位数,您需要1 /(1-p)^ 2,即对于99%的瓷砖,您需要在预热后至少10,000个样本。对于99.9%的瓷砖,你需要一百万。