临时变量与数组元素的性能,哪个更快,什么时候?



考虑以下示例,使用Python调用几个函数,使用数组元素返回一个数字:

import numpy as np
my_array = np.zeros(looplength)
for j in range(0,looplength):
temp = my_first_function(j)
my_array[j] = temp
a_1 = my_first_function(j,temp)
a_2 = my_second_function(j,temp)
a_3 = my_third_function(j,temp)
....
a_N = my_Nth_function(j,temp)

import numpy as np
my_array = np.zeros(looplength)
for j in range(0,looplength):
my_array[j] = my_first_function(j)
a_1 = my_first_function(j,my_array[j])
a_2 = my_second_function(j,my_array[j])
a_3 = my_third_function(j,my_array[j])
....
a_N = my_Nth_function(j,my_array[j])

我的问题是为了提高性能,在临时变量中使用副本还是直接访问数组元素更好,如果这种情况反复发生?另外:数组元素需要访问多少次才能使其复制速度更快?

由于my_array可以在对my_<nth>_function的调用中进行修改,因此编译器无法优化my_array[j]的每个实例,因此每次都必须执行查找。

因此,将值提取到局部变量中以供重用可能会执行得更好,这在一定程度上取决于所使用的Python编译器和使用次数。但我敢说,只要超过三次使用,可能就值得了,只是为了性能。

为了可读性,即使只有两次使用,您也可以考虑更快地执行,因为即使这稍微慢了一点(创建变量、赋值、清理),也可能会改进您的代码。但那是另一回事。

你不必相信我的话,试试这个:

from timeit import timeit

def number(x):
return x + 1

def n_times(n):
a = [0, 1, 2]
for i in range(n):
b = number(a[1])

def n_times_copied(n):
a = [0, 1, 2]
x = a[1]
for i in range(n):
b = number(x)

def main():
for n in range(10):
print(f'n is {n}, access: {timeit(lambda: n_times(n))}')
print(f'n is {n}, copied: {timeit(lambda: n_times_copied(n))}')

main()

我结果:

n is 0, access: 0.2166731
n is 0, copied: 0.22873619999999995
n is 1, access: 0.3126325000000001
n is 1, copied: 0.34623590000000004
n is 2, access: 0.4013982999999999
n is 2, copied: 0.3592341000000001
n is 3, access: 0.5191629
n is 3, copied: 0.39491809999999994
n is 4, access: 0.4818688999999998
n is 4, copied: 0.4481706000000001
n is 5, access: 0.5782233999999997
n is 5, copied: 0.5087457999999998
n is 6, access: 0.6317819
n is 6, copied: 0.5696268
n is 7, access: 0.7247358000000004
n is 7, copied: 0.6597318000000003
n is 8, access: 0.7239683000000001
n is 8, copied: 0.6870645999999994
n is 9, access: 0.8341450000000012
n is 9, copied: 0.7839662999999994

这些是在标准Python 3.9.7(我碰巧安装在我的沙箱中)上运行的结果,在Windows 10上运行英特尔酷睿i9-9900K。

请注意,有很多变化(每次调用time它运行传递的可调用对象一百万次),但对我来说,它翻转为&;n是2&;或者"n = 3",具体取决于尝试次数。

最新更新