Long For 循环执行时间

Long For Loop Excecution Time

我正在尝试将 MATLAB 脚本的数字输出与 numpy 的数字输出进行比较。

家庭作业中的任务是将 10^-N 的值与其自身相加 10^N 次

目标是证明计算机的局限性会在这样的计算中复合。结果应该总是1,但是随着N的增加,误差也会增加。对于这道题,N应该是0, 1, 2, ..., 8.

我的 MATLAB 脚本运行很快就没有问题:

solns = zeros(1, 9);

for N = 0:8
    for ii = 1:(10^N)
        solns(N+1) = solns(N+1) + 10^-N;
    end
end

但是,在带有 numpy 的 Anaconda 安装上使用 Python 3.8.12,此代码不会终止(参见更新,代码确实执行):

import numpy as np

solns = np.zeros((9, 1))

for N in range(len(solns)):
    for _ in range(10**N):
        solns[N] += (10**-N)

Python 代码中是否存在错误,或者创建此结果的语言之间是否存在一些显着差异。

编辑:

我让 python 代码 运行 了一段时间,它最终在 230 秒后终止。整个数组打印为 [1., 1., 1., etc.].

供参考,在 MATLAB 上使用 tic toc 命令,程序执行时间为 0.155760 秒

你在滥用 NumPy。特别是带有数组元素的 += 似乎几乎占用了所有时间。

我会这样做,大约需要 0.5 秒:

from itertools import repeat

for N in range(9):
    print(sum(repeat(10**-N, 10**N)))

输出(Try it online!):

1
0.9999999999999999
1.0000000000000007
1.0000000000000007
0.9999999999999062
0.9999999999980838
1.000000000007918
0.99999999975017
1.0000000022898672

正如@AndrasDeak 评论的那样,由于进行了多项优化,它的速度很快。让我们也尝试更少的优化。

首先,只摆脱 NumPy,使用简单的 Python 浮点数。顺便说一句,您原来的内容也需要我大约 230 秒。这只有大约29秒:

for N in range(9):
    total = 0
    for _ in range(10**N):
        total += (10**-N)
    print(total)

接下来,不要一遍又一遍地重新计算附加值。大约需要 11 秒:

for N in range(9):
    total = 0
    add = 10**-N
    for _ in range(10**N):
        total += add
    print(total)

接下来,摆脱 range 无缘无故地生成大量 int 对象的做法。让我们使用 itertools.repeat,这是我所知道的最快的迭代器。大约需要 9 秒:

from itertools import repeat

for N in range(9):
    total = 0
    add = 10**-N
    for _ in repeat(None, 10**N):
        total += add
    print(total)

或者,大约相同的速度:

from itertools import repeat

for N in range(9):
    total = 0
    for add in repeat(10**-N, 10**N):
        total += add
    print(total)

只需将其放入一个函数中即可受益于局部变量比全局变量更快。然后大约需要 3.3 秒:

from itertools import repeat

def run():
    for N in range(9):
        total = 0
        for add in repeat(10**-N, 10**N):
            total += add
        print(total)
run()

这可能是我用普通干净的 for 循环所能做到的最快速度(展开循环会有所帮助,但是呃...)。

我的 sum(repeat(...)) 版本让 C 代码完成所有工作(并且 sum 甚至 optimizes the summation of floats),使其仍然更快。