我的Python代码中有4个嵌套循环,当网格很大时,要花很长时间才能完成所有循环。例如,下面是我的一段代码:
from itertools import product
T = 50
beta = 0.98
alpha = 0.3
delta = 0.1
xss = ((1 / beta - (1 - delta)) / alpha)**(1 / (alpha - 1))
yss = xss**alpha
x = np.linspace(0.8 * xss, 1.4 * xss, T,dtype='float32')
y = np.linspace(yss, 1.2 * yss, T,dtype='float32')
for i,j,a,b in product(range(T),range(T),range(T),range(T)):
z[i*T+a,j*T+b] = x[i]**alpha + (1 - delta) * x[i] + y[j] - x[a] - y[b]
有没有什么解决方案可以帮助Python更快地创建矩阵z
?
2条答案
按热度按时间okxuctiv1#
Python中的循环是很慢的,尽可能地将其保存在
numpy
中,一个好的开始应该是注意到您正在创建一个基于四个参数的新矩阵;把参数转换成一个4维数组,让numpy
广播为你处理循环。这一个命令应该就是你所需要的,而且它会非常非常快:您可能会注意到,代码中与
i
索引有关的所有内容都放在了第一维([:, None, None, None]
)中;与j
有关的所有内容(按[None, None, :, None]
),等等。这将以[T, T, T, T]
形状结束,每个参数(在代码中分别为i
、a
、j
和b
)对应一个维度。之后,由于维度的顺序正确,您可以按以下方式将其折叠为[T * T, T * T]
形状结果中存在细微差别,因为我的计算完全停留在
float32
区域,而您的计算则徘徊在float64
区域,然后被迫进入z.dtype
区域(我在你的代码中看不到z
的定义)。这是因为x ** alpha
和(1 - delta) * x
将与x.dtype
保持一致,完全在numpy
内;但是x[i] ** alpha
和(1 - delta) * x[i]
就不会受到这样的限制。如果你把代码改成这样,你可以验证你得到了同样的结果:也就是说,这种加速之所以可能,是因为
x
和y
是numpy
阵列:numpy
对数字的存储效率非常高,在计算过程中不需要分配或解除分配,所有这些都是在Pythonland之外的一个非常低的级别上完成的,假设您没有在标记中指定numpy,这可能有点欺骗;但是你确实在你的代码中使用了numpy
,所以我想应该没问题。如果你对numpy
的答案没问题,那么添加numpy标记就好了。在纯Python中,你能做的最好的事情就是预先计算你能做的:
然后运行循环,将
x[i]**alpha + (1 - delta) * x[i]
替换为xi[i]
。没有其他方法可以使此过程更快。y0u0uwnf2#
首先,
product(range(T),range(T),range(T),range(T))
在python中是50^4
次迭代,其中for循环极其缓慢。缓存相同的值以避免在for循环中重复计算。
例如:
(1 - delta)
重复50^4
次x[i]**alpha
重复50^3
次代码如下: