Python 如何加速循环?

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

我试图在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*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)