Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么我的(新手)代码这么慢?_Python_Performance_Profiler - Fatal编程技术网

Python 为什么我的(新手)代码这么慢?

Python 为什么我的(新手)代码这么慢?,python,performance,profiler,Python,Performance,Profiler,我正在学习python,遇到了一个我以前见过的模型的模拟。其中一个函数看起来太长了,所以我认为提高它的效率是一种很好的做法。我的尝试虽然需要更少的代码,但速度大约是它的60分之一。是的,我让情况恶化了60倍 我的问题是,我哪里做错了?我尝试了对函数的各个部分进行计时,但没有看到瓶颈在哪里 这是原始函数。这是一个模型,人们生活在一个网格上,他们的幸福取决于他们是否与大多数邻居是同一种族。(这是谢林的。)所以我们给一个人一个x,y坐标,然后通过检查每个邻居的种族来确定他们的幸福感 def is_un

我正在学习python,遇到了一个我以前见过的模型的模拟。其中一个函数看起来太长了,所以我认为提高它的效率是一种很好的做法。我的尝试虽然需要更少的代码,但速度大约是它的60分之一。是的,我让情况恶化了60倍

我的问题是,我哪里做错了?我尝试了对函数的各个部分进行计时,但没有看到瓶颈在哪里

这是原始函数。这是一个模型,人们生活在一个网格上,他们的幸福取决于他们是否与大多数邻居是同一种族。(这是谢林的。)所以我们给一个人一个x,y坐标,然后通过检查每个邻居的种族来确定他们的幸福感

def is_unhappy(self, x, y):

    race = self.agents[(x,y)]
    count_similar = 0
    count_different = 0

    if x > 0 and y > 0 and (x-1, y-1) not in self.empty_houses:
        if self.agents[(x-1, y-1)] == race:
            count_similar += 1
        else:
            count_different += 1
    if y > 0 and (x,y-1) not in self.empty_houses:
        if self.agents[(x,y-1)] == race:
            count_similar += 1
        else:
            count_different += 1
    if x < (self.width-1) and y > 0 and (x+1,y-1) not in self.empty_houses:
        if self.agents[(x+1,y-1)] == race:
            count_similar += 1
        else:
            count_different += 1
    if x > 0 and (x-1,y) not in self.empty_houses:
        if self.agents[(x-1,y)] == race:
            count_similar += 1
        else:
            count_different += 1        
    if x < (self.width-1) and (x+1,y) not in self.empty_houses:
        if self.agents[(x+1,y)] == race:
            count_similar += 1
        else:
            count_different += 1
    if x > 0 and y < (self.height-1) and (x-1,y+1) not in self.empty_houses:
        if self.agents[(x-1,y+1)] == race:
            count_similar += 1
        else:
            count_different += 1        
    if x > 0 and y < (self.height-1) and (x,y+1) not in self.empty_houses:
        if self.agents[(x,y+1)] == race:
            count_similar += 1
        else:
            count_different += 1        
    if x < (self.width-1) and y < (self.height-1) and (x+1,y+1) not in self.empty_houses:
        if self.agents[(x+1,y+1)] == race:
            count_similar += 1
        else:
            count_different += 1

    if (count_similar+count_different) == 0:
        return False
    else:
        return float(count_similar)/(count_similar+count_different) < self.similarity_threshold 

我希望有python知识的人能够立即看到我做错了什么,而不必深入了解其余代码的细节。你能理解为什么我的代码比原来的代码糟糕得多吗?

罪魁祸首似乎是这一行:

neighbor = tuple(np.add( (x,y), (xo,yo) ))
将其更改为此将显示巨大的加速:

neighbor = (x + xo, y + yo)

不要使用
np。添加
,只使用
邻居=(x+xo,y+yo)
。这将使它更快(在我的小测试中快10倍)

你也可以

  • 询问self.agents中的邻居:
而不使用
.keys()
  • 省略
    列表
  • 选中
    xo或yo
    ,并且没有空的if块
  • 避免在自代理中重复查找邻居
  • 结果:

    for xo, yo in itertools.product([-1,0,1],[-1,0,1]):
        if xo or yo:
            neighbor = self.agents.get((x+xo, y+yo))
            if neighbor is not None:
                if neighbor == thisRace:
                    count_same += 1
                else:
                    count_other += 1
    
    你可以加上

    self.neighbor_deltas = tuple(set(itertools.product([-1,0,1],[-1,0,1])) - {(0, 0)})
    
    到类初始值设定项,然后您的函数可以只使用这些预先计算的增量:

    for xo, yo in self.neighbor_deltas:
        neighbor = self.agents.get((x+xo, y+yo))
        if neighbor is not None:
            if neighbor == thisRace:
                count_same += 1
            else:
                count_other += 1
    

    恭喜你决定改进这位作者荒谬重复的代码,顺便说一句。

    你的代码慢吗?每循环5.99毫秒时的100个循环总计599毫秒,103微秒时的10000个循环总计1030毫秒。也许我被计时结果弄糊涂了?@ryan重要的是每个循环的时间,而不是运行基准测试所花费的总时间。迭代次数只是给你一个置信区间的概念。@TylerH有9次向上投票,到目前为止没有接近投票,这似乎是一个可以接受的堆栈溢出问题。有些问题可以在这两个网站上讨论。这也不是一个很好的代码审查问题,因为它包含了一点关于理解其他代码的内容。在别的地方谈论话题并不能使它偏离话题。@TylerH@RubberDuck说它属于其他地方并不是一个很接近的理由。不幸的是,即使根据新的信息,我们也不能改变我们的简历理由,所以我不能这样做。
    self.neighbor_deltas = tuple(set(itertools.product([-1,0,1],[-1,0,1])) - {(0, 0)})
    
    for xo, yo in self.neighbor_deltas:
        neighbor = self.agents.get((x+xo, y+yo))
        if neighbor is not None:
            if neighbor == thisRace:
                count_same += 1
            else:
                count_other += 1