python 中的这种操作是否为我的低效程序节省了更多时间?

Does this manipulation in python save more time for my highly inefficient program?

我正在使用以下代码,形式不变但内容有所改变:

import numpy as np
import matplotlib.pyplot as plt
import random
from random import seed
from random import randint
import math
from math import *
from random import *
import statistics
from statistics import *


n=1000
T_plot=[0];
X_relm=[0];
 
class Objs:
    def __init__(self, xIn, yIn, color):
      self.xIn= xIn
      self.yIn = yIn
      self.color = color
    def yfT(self, t):
       return self.yIn*t+self.yIn*t
    def xfT(self, t):
       return self.xIn*t-self.yIn*t
xi=np.random.uniform(0,1,n);
yi=np.random.uniform(0,1,n);

O1 = [Objs(xIn = i, yIn = j, color = choice(["Black", "White"])) for i,j 
      in zip(xi,yi)]
X=sorted(O1,key=lambda x:x.xIn)     
 
dt=1/(2*n)
T=20
iter=40000
Black=[]
White=[]
Xrelm=[]        
for i in range(1,iter+1):
     t=i*dt
     for j in range(n-1):
       check=X[j].xfT(t)-X[j+1].xfT(t);
       if check<0:
          X[j],X[j+1]=X[j+1],X[j]
          if check<-10:
             X[j].color,X[j+1].color=X[j+1].color,X[j].color  
       if X[j].color=="Black":
            Black.append(X[j].xfT(t))
       else:
            White.append(X[j].xfT(t))
     Xrel=mean(Black)-mean(White)
     Xrelm.append(Xrel)

plot1=plt.figure(1);
plt.plot(T_plot,Xrelm);
plt.xlabel("time")
plt.ylabel("Relative ") 

并且它保持 运行ning(我把它放置了 10 个小时)而没有给出某些参数的输出,我猜是因为它太大了。我知道我的代码并没有完全错误(在某种意义上它应该给出 一些东西 即使错误)因为它确实给出了更少的时间步长和其他参数的输出。

所以,我正专注于尝试优化我的代码,以便花费更少的时间 运行。现在,这是编码人员的例行任务,但我是新手,我编写代码只是因为模拟对我的领域有帮助。因此,总的来说,任何能提供有关如何使代码更快的见解的一般性输入都会受到赞赏。

除此之外,我想问一下为内循环定义一个先验函数是否会节省任何时间。

我认为它不会节省任何时间,因为我正在做同样的事情,但我不确定是否可以。如果没有,我们将不胜感激任何关于如何以更有效的方式处理嵌套循环以及一般性质的循环的见解。

(我尽量缩短了代码,但仍然没有遗漏相关信息)

正如之前评论中提到的,这个问题太宽泛了,无法回答。

举例说明;您的迭代本身不会花费很长时间:

import time


start = time.time()

for i in range(10000):
    for j in range(10000):
        pass

end = time.time()
print (end-start)

在我的 not-so-great 机器上需要 ~2 秒才能完成。

所以循环部分只是你 10 小时以上 运行 时间的一小部分。

你在循环中什么的细节是关键。

虽然非常基础,但我在上面的代码中展示的方法可以应用于您现有的代码,以找出性能最低的位,然后提出一个更具体、可操作的新问题细节。

您的代码中存在几个问题:

  • 根据不断增长的数组从头开始重新计算平均值。因此,mean(Black)-mean(White) 的复杂度是元素数量的 二次方
  • mean 函数效率不高。使用基本的 sum 和除法要快得多。事实上,手动平均在我的机器上快了大约 25~30 倍。
  • CPython 解释器非常慢 所以你应该尽可能避免使用循环(OOP 代码也无济于事)。如果这是不可能的并且您的计算成本很高,那么请考虑使用本机 编译的 代码。您可以使用 PyPy、Numba 或 Cython 等工具,也可以用 C 语言重写一部分。
  • 请注意,字符串通常很慢,没有理由在这里使用它们。考虑改用枚举(即整数)。

这是修复前两点的代码:

dt = 1/(2*n)
T = 20
iter = 40000
Black = []
White = []
Xrelm = []
cur1, cur2 = 0, 0
sum1, sum2 = 0.0, 0.0

for i in range(1,iter+1):
    t = i*dt
    for j in range(n-1):
        check = X[j].xfT(t) - X[j+1].xfT(t)
        if check < 0:
            X[j],X[j+1] = X[j+1],X[j]
            if check < -10:
                X[j].color, X[j+1].color = X[j+1].color, X[j].color
            if X[j].color == "Black":
                Black.append(X[j].xfT(t))
            else:
                White.append(X[j].xfT(t))
    delta1, delta2 = sum(Black[cur1:]), sum(White[cur2:])
    sum1, sum2 = sum1+delta1, sum2+delta2
    cur1, cur2 = len(Black), len(White)
    Xrel = sum1/cur1 - sum2/cur2
    Xrelm.append(Xrel)

如果您以后不使用它们,请考虑将 BlackWhite 重置为空列表。

快了数百倍。现在,初始代码需要 2 分钟,而不是 >20 小时(估计)。

注意这里使用编译后的代码至少要快10倍所以执行时间应该不会超过几十秒