所以我在汇编中编写素数生成器(学习语言),当我开始对程序进行基准测试时,我发现它是在线性时间而不是预期的O(N * sqrt(N))
时间运行。
为什么会这样?
我仔细检查了代码并将其放在github上:https://github.com/kcolford/assembly_primes。它应该是相当可读的,但如果有人希望我更彻底地评论它(比如对每条指令的解释)我很乐意这样做,我只是觉得没有必要。
我正在使用的汇编器和链接器是GNU binutils中的汇编器和链接器,它是为运行linux内核的x86_64架构编写的。
答案 0 :(得分:2)
通过实验测量Big-O复杂性很棘手。就像菲尔佩里所说的那样,通常有线性术语(或其他术语)压倒了“小”运行的主要 O ()术语。隐藏在big-O表示法中的这些额外术语总是存在于实际代码中,在分析实际运行时间时是必需的。
当我在测试机器上测量您的示例代码时,我得到了明显的非线性关系。由于名声不好,我无法发布情节,但这是一张表:
N (= n^2) Time
1000000 0.386
4000000 1.846
9000000 4.673
16000000 9.275
25000000 15.850
36000000 24.690
49000000 35.850
64000000 49.887
81000000 66.509
100000000 86.855
此外,我没有仔细查看您的算法的确切实现,但Sieve of Eratosthenes是O( n 日志日志 n ),而不是O( n sqrt( n ))。
另请注意,与数字运算相比,I / O通常非常昂贵。在您的情况下,在我的测试计算机上, n = 5000时,I / O几乎占总运行时间的30%。这将是运行时分析中的重要线性项。你必须彻底分析代码正在做的其他事情,以找出影响测量的其他因素。