为什么要使用比较而不是运行时来比较两种算法?


19

我注意到在一些CS研究论文中,为了比较两种算法的效率,使用了算法中密钥比较的总数,而不是实际的计算时间本身。我们为什么不能通过运行两个程序并计算运行算法所需的总时间来比较哪个更好呢?


欢迎!我希望大多数此类论文都不要使用运行时。不过,我知道有些人做得到,特别是在应用更为广泛的社区以及所考虑的系统非常复杂的情况下。
拉斐尔

Answers:


14

这实际上是一个深层次的问题,有一些方法性的和务实的答案。我假设您想了解手头的算法。如果您想知道哪种算法在给定输入下的给定机器上效果更好,请继续并测量运行时间。如果要比较给定算法的编译器质量,请继续并测量运行时间。要了解有关该算法的知识,请不要这样做。

让我首先说明为什么使用运行时不是一个好主意。


  1. 如果更改任何组件,则在一台机器上使用一种语言和一种编译器测得的通用运行时间几乎没有意义。即使是同一算法的稍有不同的实现,其执行效果也会有所不同,这是因为您触发了某些情况下的编译器优化,而没有触发其他情况。
  2. 预测
    因此,您需要为某些输入提供几个运行时。那如何说明其他一些输入的运行时间?一般来说,什么都没有。
  3. 重要性
    通常,您不会对所有输入(一定大小)进行基准测试,从而立即限制了您比较算法的能力:也许您的测试集在一种算法中触发了最坏的情况,而在另一种算法中触发了最坏的情况?也许您的输入太小而无法表现出运行时行为
  4. 计量很好地
    测量运行时间非易事。有准时服务吗?是否存在争用,即您是否在计算算法甚至没有运行的时间?您可以为另一次运行(另一种算法),特别是并发进程和缓存重现完全相同的计算机状态吗?内存延迟如何处理?

我希望这些使您相信,运行时是比较算法的可怕方法,并且需要一些通用的抽象方法来调查算法运行时。

接下来是问题的第二部分。为什么我们使用比较或类似的基本运算?

  1. 易分析性
    假设您想进行形式分析,则必须能够进行。计算单个语句的技术性很强,有时甚至很难。尽管如此,仍有一些人(例如Knuth)这样做。仅计算某些语句(支配运行时的语句)更加容易。出于相同的原因,我们经常“仅”调查(上限)最坏情况下的运行时。

  2. 优势
    所选操作主导运行时间。这并不意味着它贡献了最多的运行时间-比较显然没有作用,例如在对单词大小的整数进行排序时在Quicksort中。但是它们执行得最频繁,因此通过对它们进行计数,您可以计算出算法中执行最频繁的部分的运行频率。因此,您的渐近运行时与主要基本运算的数量成正比。这就是为什么即使我们只计算比较,我们也可以轻松使用Landau表示法和“运行时”一词。

请注意,计数多个操作可能很有用。例如,某些Quicksort变体进行比较的次数多,但交换次数却少(平均)。

值得一说的是,在完成所有理论之后,您可能希望重新访问运行时,以验证理论所做的预测是正确的。如果它们没有用,那么您的理论(在实践中)将无用,必须加以扩展。内存层次结构是您首先意识到的重要内容之一,但是在基本分析中却没有。


1
请记住,形式分析也有其局限性。例如,非均匀输入分布的平均情况通常很棘手。
拉斐尔

10

这是因为运行算法的总时间取决于运行该算法的硬件以及其他因素。如果一个在奔腾4上运行而另一个在Core i7上运行,则比较两种算法是不可靠的。不仅如此,还可以说您都在同一台计算机上运行。两者的处理器时间相同是什么意思?如果某个其他进程的优先级高于其中一种算法的进程,会发生什么情况?

为了克服这个问题,我们将这个总时间与完成时间分开,而是根据算法的扩展程度进行比较。您可能已经在研究论文中注意到了诸如O(1)或O(n ^ 2)之类的符号。如果您有兴趣查看Big O标记,这可能需要更多阅读。


1
实际的运行时间还取决于运行算法的实际输入的大小和内容!
伊藤刚(Tsuyoshi Ito)

7

由于其他答案解释了为什么我们要根据基本运算的数量来分析运行时,因此让我提供一些原因,说明为什么比较是许多(并非全部)排序算法的正确指标:

  • 对于许多排序算法,比较次数决定了运行时间,即,至少执行了与其他任何基本操作一样多的比较
  • 比较是昂贵的操作;考虑一下如何在库中实现排序例程:将数组元素和指向比较两个元素的函数的指针传递给sort函数;通常,调用和等待比较函数执行比“内部”操作昂贵。由于此功能由用户提供,因此很难对其进行优化
  • (这可能是一个好理由,也可能不是一个好理由),我们可以足以对序列进行排序的比较次数说些有趣的话;我们知道如何在最坏的情况下平均分配各种分布,甚至设计一种在未知分布的iid采样项上运行时收敛到最优的算法(自我改进算法);我们知道免费提供一些比较时如何执行此操作(使用部分信息排序

1)“至少执行与任何其他基本操作一样多的比较” –仅限于一个恒定因子。2)“比较是昂贵的操作”-假定使用通用设置。对于整数排序(通常进行分析),交换通常会更昂贵。
拉斐尔

当然。op似乎对一般的算法分析感到困惑,不想带来恒定的因素。我希望我说的是一个通用的设定其实是从描述清楚-排序过程的标准库是不是整数排序
Sasho尼科洛夫

加上op看到的论文绝对不是关于专门的整数排序算法的,没有人计算比较的次数
Sasho Nikolov 2012年

@Raphael对小整数进行排序在实践中并不常见。我认为世界上进行的大多数排序都是基于字符串(一定长度或其他长度)。即使对于整数排序,我也不确定交换是否更昂贵-分支是现代高端处理器上相对昂贵的操作,因为看到分支预测在排序时几乎没有用。
吉尔斯(Gilles)“所以别再作恶了”

@Gilles本身,交换比整数比较要昂贵,比我所知道的任何平台都要昂贵。诸如分支错误预测之类的“二次”成本无疑是一个因素,其影响是正在进行的研究的主题。(关于在实践中的使用,我无法做出合格的声明。但是,我观察到标准库维护人员不断改进他们用于原始数据类型的排序算法,因此我认为他们看到了很多(滥用)使用情况。)
Raphael
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.