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),使其仍然更快。
我正在尝试将 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),使其仍然更快。