硬件/实现会影响算法的时间/空间复杂度吗?


32

我什至都不是CS学生,所以这可能是一个愚蠢的问题,但是请忍受...

在前计算机时代,我们只能用抽屉数组来实现数组数据结构。由于一个有定位与从它提取值之前对应的索引的抽屉,阵列查找的时间复杂度是,假设二进制搜索。ØØGñ

但是,计算机的发明产生了很大的变化。现代计算机可以如此快速地从其RAM中读取数据,因此我们现在认为数组查找的时间复杂度为(即使从技术上讲也不是这种情况,因为将寄存器移至更远的距离需要花费更多时间,等等)Ø1个

另一个例子是Python字典。虽然人们可能会得到一本字典访问的复杂性与病人写重载魔术方法(或可笑的坏运气,即具有大量的散列冲突的键),它通常被认为是Ø 1 。在这种情况下,时间复杂度既取决于Python字典的哈希表实现,也取决于哈希函数的键的实现。Øñ__hash__Ø1个

这是否意味着硬件/实现会影响算法的时间复杂度?(虽然这两个示例都是关于数据结构而不是算法,但后者是建立在前者之上的,而且我从未听说过数据结构的时间复杂性,因此在这里我使用术语“算法”)

对我来说,算法是抽象的和概念性的,它们的属性(例如时间/空间复杂度)不应受到是否以特定方式实现而受到影响,但它们是吗?


评论不作进一步讨论;此对话已转移至聊天
吉尔斯(Gillles)“所以-别再作恶了”

Answers:


42

当然。当然。这是解决您不适的方法。

当我们分析算法的运行时间时,我们是针对特定的计算模型进行的。计算模型指定诸如执行每个基本操作所需的时间之类的东西(是数组查找时间还是O 1 时间?)。算法的运行时间可能取决于计算模型。Ø日志ñØ1个

选择了计算模型后,对算法的分析就是一种纯粹的抽象,概念性,数学练习,不再依赖硬件。

但是,在实践中,我们通常希望选择一种能够反映我们硬件实际情况的计算模型-至少在合理的程度上。因此,如果硬件发生变化,我们可能会决定在更适合新硬件的不同计算模型下分析算法。这就是硬件如何影响运行时间的方式。

之所以不那么明显,是因为在入门类中,我们通常不谈论计算模型。我们只是隐含地做出一些假设,而没有明确地做出假设。出于教学目的,这是合理的,但是要付出代价-掩盖了分析的这一方面。现在你知道了。


如您所说,我们将随机访问模型用作计算模型,但是当我们使用GPU进行某些计算时,某些算法的时间复杂度会随着使用SIMD指令而改变。
Deep Joshi

6
还要注意,O()表示法是一个上限。即使您使用抽屉类比,找到一个有限大小的抽屉(实际内存的大小也受限制),构建仍需要O(1)时间。即使您花费20分钟到达最远的抽屉(所有高速缓存未命中,甚至您必须从swap加载数据)仍然是O(1)时间,因为20分钟将是您访问内存的隐藏常数。
Goswin von Brederlow

2
Ø1个Øñ

1
@CortAmmon:即使在大型数组上,如果要搜索的元素中除少数元素以外的所有元素都非常接近开始,那么使用线性搜索可能比使用哈希映射更快。例如,如果50%的元素与第一个元素匹配,25%的元素与第二个元素匹配,12.5%的元素与第三个元素匹配,依此类推,除了一个奇数元素将匹配数组中可能存在的任何东西,预期与之比较的次数在大小为N的列表上执行M个查找将是2M + N。
超级猫

5
@DeepJoshi SIMD指令不会改变算法的复杂性。它们仅更改乘法常数。
吉尔斯(Gillles)“所以-别再邪恶了”

5

我认为这个问题有一个基本的误解。您将一个人在排序列表(例如,书中的特定页面,已给出其编号)中找到对象的情况与计算机从数组中查找项目的结果进行比较。

Ø日志ñØ1个

因此,是的,正如DW解释的那样,硬件(即计算模型)确实会影响算法的运行时间,但这并不是您的数组访问示例所基于的。


2
公平地说,您跳过了“内存控制器将地址线上的电压设置为17的二进制表示形式”和“数据返回”之间的所有内容。这些碎片之一几乎可以肯定 OP描述的那种二进制搜索树。但是它仍然以恒定的时间执行,因为对于所有n来说log n大约为64
Quuxplusone

@Quuxplusone存储器的哪一部分使用二进制搜索?地址线直接选择存储单元。
David Richerby

我们的工作范围远远超出我的专业知识范围,但是我想暗示的是,将使用多路分解来实现地址解码器。(假设我们直接访问物理内存,而忽略了缓存带来的任何额外的复杂性。)同样,所有这些额外的复杂性仅增加了O(lg size-of-memory),即可以忽略不计,但这恰恰是OP所要求的!
Quuxplusone

2

不,硬件不会影响算法的复杂性。

但是,它确实会影响算法的选择,并且会影响复杂度分析的有用性,以至于分析变得毫无意义(或仅具有学术意义)。

查找正确的抽屉(访问数组元素)使用“直接通过索引打开第N个元素”算法,而不是“线性搜索”或“进行二进制搜索”算法。算法没有改变,而是选择。

另一方面,复杂性分析本身或它的意义受到硬件的极大影响

许多因复杂性分析而出色的算法在实践中表现不佳,甚至无用,因为无关紧要的常数因素并非无关紧要,而是占主导地位的

或者,因为曾经是真实的(或大体上是真实的)假设不再成立。例如,每个操作几乎都是相同的(只是无关紧要的小常数差异),或者按顺序访问哪个内存位置都没有影响。通过复杂性分析,您可能会得出结论,某些算法要优越得多,因为它只需要这么多的操作。在实践中,您可能会发现每个操作都会导致保证的高速缓存未命中(或者更糟糕的是,页面错误),这引入了一个很大的k,不再是无关紧要的,而是主导了一切。
如果算法A需要500次操作来处理给定大小的数据集,而算法B仅需要5次操作,但是B导致5个故障,每个故障燃烧2000万个周期,那么尽管分析或常识可能告诉您,A还是更好。

这导致了一些有趣的惊喜,例如几年前的Cuckoo Hashing。这是非常优越的,因为[好处很多]。炒作冷却之后,事实证明它是次等的,因为它保证了每次访问都会导致两次高速缓存未命中(对于较大的数据集,将发生故障)。

识别和处理数据子集的过程也类似。如今,当今正确的解决方案通常是:“全力以赴”,即,不用弄清楚您要进行的工作并做到这一点,就可以线性地处理整个数据集,即使您只需要一半即可。因为(不管您相信与否),由于没有分支预测错误,没有缓存丢失,没有页面错误,因此速度更快。
是否需要读取3MB文件的前8kB和后3kB?好吧,请阅读完整的文件,并丢弃您不想要的文件,因为在两者之间进行查找将比仅阅读完整的文件慢十倍。

使用地图是因为它具有对数复杂性?还是具有恒定访问时间的哈希表?常数听起来很棒。好吧,对于少于一千个事物的任何事物(取决于硬件,数据大小和访问模式),线性搜索可能会同样好或更好。惊喜

因此,受影响的不是算法本身,而是它们的用途和选择。

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.