Python 如何加速循环?
我试图在python中加速这个for循环,其中N是一个大约12000的大数字。此循环运行时间超过20秒。计算cossum和sinsum的线条似乎是这里的主要罪魁祸首。我如何优化它,使其运行更快 (我对编码相当陌生,因此非常感谢您提供一个简单的解释!谢谢) 范围(N)内的i的Python 如何加速循环?,python,for-loop,optimization,Python,For Loop,Optimization,我试图在python中加速这个for循环,其中N是一个大约12000的大数字。此循环运行时间超过20秒。计算cossum和sinsum的线条似乎是这里的主要罪魁祸首。我如何优化它,使其运行更快 (我对编码相当陌生,因此非常感谢您提供一个简单的解释!谢谢) 范围(N)内的i的: 余数=0 sinsum=0 sq=k_数组[i][0]**2+k_数组[i][1]**2+k_数组[i][2]**2 如果平方为0: kvec_used=kvec_used+1 肯德基[i]=np.exp(-sq/(4*b
:
余数=0
sinsum=0
sq=k_数组[i][0]**2+k_数组[i][1]**2+k_数组[i][2]**2
如果平方为0:
kvec_used=kvec_used+1
肯德基[i]=np.exp(-sq/(4*beta**2))/(sq)
对于范围内的j(场地):
cossum=cossum+q_数组首字母[j]*np.cos(np.dot(k_数组[i],r_数组首字母[j]))
sinsum=sinsum+q_数组首字母[j]*np.sin(np.dot(k_数组[i],r_数组首字母[j]))
cos_部分=(abs(cossum))**2
sinu部分=(abs(sinsum))**2
您可以使用Numpy中的矢量化删除代码中的所有for
循环。我建议你开始沿着这条路冒险时阅读
我以您的示例为例,使用random
生成了一些垃圾数据来代替数组和变量
import numpy as np
import random
import time
kvec_used = 0
k_array = []
sqmax = 10
beta = .5
kfac = []
sites = 3
q_array_initial = r_cart_initial = [.1, .2, .3]
for i in range(12000):
temp = [random.random(), random.random(), random.random()]
k_array.append(temp)
kfac.append(random.random())
mytime = time.time()
for i in range(12000):
cossum = 0
sinsum = 0
sq = k_array[i][0]**2 + k_array[i][1]**2 + k_array[i][2]**2
if sq <= sqmax and sq>0:
kvec_used = kvec_used + 1
kfac[i] = np.exp(-sq/(4*beta**2))/(sq)
for j in range(sites):
cossum = cossum + q_array_initial[j]*np.cos(np.dot(k_array[i],r_cart_initial[j]))
sinsum = sinsum + q_array_initial[j]*np.sin(np.dot(k_array[i],r_cart_initial[j]))
cos_part = (abs(cossum))**2
sin_part = (abs(sinsum))**2
print("looped", time.time() - mytime)
mytime = time.time()
k_array = np.asarray(k_array)
sq = np.square(k_array[:, 0]) + np.square(k_array[:, 1]) + np.square(k_array[:, 2])
sq = sq[np.where(np.logical_and(sq[:] <= sqmax, sq[:] > 0))]
kvec = np.shape(sq)[0]
kfac = np.exp(-sq[:]/(4*beta**2))/(sq[:])
for j in range(sites):
cossum = cossum + q_array_initial[j]*np.cos(np.dot(k_array[i],r_cart_initial[j]))
sinsum = sinsum + q_array_initial[j]*np.sin(np.dot(k_array[i],r_cart_initial[j]))
cos_part = (abs(cossum))**2
sin_part = (abs(sinsum))**2
print("vectorized:", time.time() - mytime)
当对第二个循环进行矢量化时,应该能够加快速度
编辑:我刚刚意识到你在原来的问题中要求更多的解释。我在上面链接的这篇文章详细地解释了这一点,也是我第一次开始对大型数据集进行矢量化时使用的内容。然而,我可以提供一个超级简单的解释,让你来到这里: 当您有一个大数组时,在Python中运行
for
循环实际上有点慢。Numpy在幕后使用了一些更高级的代码,这些代码可以比在for
循环中按顺序运行操作更快。对于初学者来说,您可以接受Numpy暂时是“魔法”。这里最大的收获是,您不需要遍历并操作数组中的i
th元素,而是希望告诉Numpy对整个元素进行操作,表示为myarray[:]
。您可以将其扩展到多维数组。完整的二维数组是myarray[:,:]
。如果(以电子表格的方式思考)您只想对2d数组中的第0列和所有行进行操作,这将成为myarray[:,0]
在这里,我使用了奇特的特定于Numpy的方法where
和logical\u和
来替换您的if
conditional。这是另一种矢量化技术,它能够比迭代方法更快地处理条件语句
我故意让第二个
for
循环未翻译,作为练习。没有人能不受痛苦地学习!您在这里使用np.cos
和np.sin
做得很好,但是您以迭代的方式使用它们。使用向量方法在结果向量的所有元素上运行这些数学运算符。使用向量化而不是for循环,除非您必须开发您的作为建议,否则您无法加快速度。您可以尝试使用time
模块来确定循环的哪个部分平均花费的时间最长。然后,尝试优化这些块中的代码(例如,看看问题是否出在cossum
和sinsum
上)。就目前而言,这个问题非常广泛。谢谢,我这样做了,发现大部分时间(大约19秒)都存在问题计算cossum和sinsum是一个很好的矢量化示例,有很好的参考支持。+1给你很好的sir谢谢-真的很好的解释!我正在尝试第二个循环。我尝试对k_数组
和k_数组使用[:]。k_数组=k_数组[np.where…]
)和r\u cart\u initial
但它们是不同的维度,因此不起作用。然后我列出了k\u数组
和r\u cart\u initial
的索引组合,但是我对如何避免循环感到困惑。有什么提示吗?k\u数组[np.where…]
步骤实际上删除了产生不正确结果的行,这将改变数组的大小。也许可以尝试反转逻辑,将不正确的值替换为n/a
,而不是删除。此外,我假设q\u array\u initial
的大小与k\u array
的大小不同。在这种情况下,您可以我想看看广播不同形状的数组的方法。<代码> KyLaule是不同的大小,无论是<代码> QyalayyRead < /Cord>和<代码> R.CARTILIGION< /COD>,广播会允许我考虑所有的组合吗?<代码> KyLauns和其他数组?-是的,但是你应该“欺骗”。通过重复行在一维中创建一个大小相等的新数组,例如,对于一维数组,如a=[[0,1]]
和B=[[3,4,5]]
,使用numpy repeat/tile和最终看起来像AA=[0,1,0,1,0,1]
和BB=[[3,4,5,3,4,5]]
。你的句子看起来不完整。作为评论,它可能勉强可以接受,但肯定不能作为答案。
import numpy as np
import random
import time
kvec_used = 0
k_array = []
sqmax = 10
beta = .5
kfac = []
sites = 3
q_array_initial = r_cart_initial = [.1, .2, .3]
for i in range(12000):
temp = [random.random(), random.random(), random.random()]
k_array.append(temp)
kfac.append(random.random())
mytime = time.time()
for i in range(12000):
cossum = 0
sinsum = 0
sq = k_array[i][0]**2 + k_array[i][1]**2 + k_array[i][2]**2
if sq <= sqmax and sq>0:
kvec_used = kvec_used + 1
kfac[i] = np.exp(-sq/(4*beta**2))/(sq)
for j in range(sites):
cossum = cossum + q_array_initial[j]*np.cos(np.dot(k_array[i],r_cart_initial[j]))
sinsum = sinsum + q_array_initial[j]*np.sin(np.dot(k_array[i],r_cart_initial[j]))
cos_part = (abs(cossum))**2
sin_part = (abs(sinsum))**2
print("looped", time.time() - mytime)
mytime = time.time()
k_array = np.asarray(k_array)
sq = np.square(k_array[:, 0]) + np.square(k_array[:, 1]) + np.square(k_array[:, 2])
sq = sq[np.where(np.logical_and(sq[:] <= sqmax, sq[:] > 0))]
kvec = np.shape(sq)[0]
kfac = np.exp(-sq[:]/(4*beta**2))/(sq[:])
for j in range(sites):
cossum = cossum + q_array_initial[j]*np.cos(np.dot(k_array[i],r_cart_initial[j]))
sinsum = sinsum + q_array_initial[j]*np.sin(np.dot(k_array[i],r_cart_initial[j]))
cos_part = (abs(cossum))**2
sin_part = (abs(sinsum))**2
print("vectorized:", time.time() - mytime)