利用多线程/内核提高性能

2024-09-22 16:23:36 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个游戏(使用pygame),我想提高性能。我注意到当我的fps低的时候,游戏最多只占用了20%的CPU,有没有办法让线程占用更多的CPU?你知道吗

我已经尝试实现线程,但似乎没有好运气,一些帮助将不胜感激。你知道吗

此函数是导致延迟的原因:

第一版

def SearchFood(self):
    if not self.moving:
        tempArr = np.array([])

        for e in entityArr:
            if type(e) == Food:
                if e.rect != None and self.viewingRect != None:
                    if self.viewingRect.colliderect(e.rect):
                        tempArr = np.append(tempArr, e)

        if tempArr.size > 0:
            self.nearestFood = sorted(tempArr, key=lambda e: Mag((self.x - e.x, self.y - e.y)))[0]

第二个版本(较慢)

def SearchFood(self):
    if not self.moving:
        s_arr = sorted(entityArr, key=lambda e: math.hypot(self.x - e.x, self.y - e.y))

        for e, i in enumerate(s_arr):
            if type(e) != Food:
                self.nearestFood = None

            else:
                self.nearestFood = s_arr[i]
                break

我浏览了整个实体列表,并对其进行排序,如果实体是食物,以及与想吃食物的物体的距离。问题是实体数组有500个元素(甚至更多)长,因此遍历和排序需要很长时间。然后,为了弥补这个问题,我想通过使用线程来使用更多的CPU。你知道吗

如果有帮助的话,下面是完整的脚本:https://github.com/Lobsternator/Game-Of-Life-Esque.git


Tags: self实体none游戏ifdefnpnot
2条回答

在Python中,线程并不会增加所用内核的数量。您必须改用多重处理。
文件:https://docs.python.org/3.7/library/multiprocessing.html#multiprocessing.Manager

Python中的多线程几乎是无用的(对于这样的CPU密集型任务),而多线程虽然可行,但需要在进程之间进行昂贵的数据封送或仔细的设计。我认为这两个都不适用于你的案子。你知道吗

但是,除非游戏中有大量的对象,否则不需要在场景中使用多个核心。问题似乎更多的是算法的复杂性。你知道吗

您可以通过以下几种方式提高代码的性能:

  • 按类型保留实体索引(例如,从实体类型到实体集的dict,在创建/删除实体时更新),这将允许您轻松找到所有“食物”实体,而无需扫描游戏中的所有实体。你知道吗
  • 使用简单的“min”操作(即O(n))查找最近的食物实体,而不是按距离(即O(n*logn))对所有食物进行排序。
    • 如果这仍然很慢,您可以应用剔除技术,首先将食物过滤到容易计算的范围内的食物(例如,播放器周围的矩形),然后通过仅对这些食物应用更昂贵的距离计算来查找最近的食物。你知道吗
  • 避免检查循环中不必要的条件,尽可能使用内置的选择/创建结构,而不是遍历大型对象列表,从而使循环更紧密。你知道吗

例如,你可以得到如下结果:

def find_nearest_food(self):
  food_entities = self._entities_by_type[Food]
  nearest_food = min(food_entities, key=lambda entity: distance_sq(self, entity))
  return nearest_food

def distance_sq(ent1, ent2):
  # we don't need an expensive square root operation if we're just comparing distances
  dx, dy = (ent1.x - ent2.x), (ent1.y - ent2.y)
  return dx * dx + dy * dy

您可以通过将实体位置保持为NumPy向量而不是单独的xy属性来进一步优化,这将允许您使用NumPy操作来计算距离,例如distance_sq = (ent1.pos - ent2.pos)**2或只使用np.linalg.norm进行常规距离计算。这对于其他向量算术运算也很有用。你知道吗

相关问题 更多 >