Повышение производительности благодаря использованию нескольких потоков / ядер - PullRequest
4 голосов
/ 10 апреля 2019

У меня есть игра (использующая pygame), для которой я хочу улучшить производительность.Я заметил, что когда у меня низкий fps, игра использует максимум 20% процессора, есть ли способ использовать потоки, чтобы использовать больше процессора?

Я уже пытался реализовать потоки,но, похоже, не повезло, некоторая помощь будет оценена.

Эта функция вызывает задержку:

Первая версия

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 элементов (и более), и, следовательно, для его перебора и сортировки требуется очень много времени.Затем исправить то, что я хочу использовать больше процессора с использованием потоков.

Вот полный сценарий, если это поможет: https://github.com/Lobsternator/Game-Of-Life-Esque.git

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Многопоточность в Python практически бесполезна (для таких задач с интенсивным использованием ЦП, как эта), а многопроцессорность, хотя и жизнеспособная, требует дорогостоящего распределения данных между процессами или тщательного проектирования.Я не верю, что одно из них применимо к вашему случаю.

Однако, если в вашей игре нет большого количества объектов, вам не нужно использовать несколько ядер для вашего сценария.Проблема, кажется, больше связана с алгоритмической сложностью.

Вы можете улучшить производительность своего кода несколькими способами:

  • Хранить индекс объектов по типу (например, переход от типа объекта к набору объектов, который вы обновляетекак объекты создаются / удаляются), что позволит вам легко находить все "пищевые" объекты, не просматривая все объекты в игре.
  • Найти ближайший пищевой объект, используя простую операцию "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 вместо отдельных свойств x и y, что позволит вам использовать операции NumPy длярассчитать расстояние, например, distance_sq = (ent1.pos - ent2.pos)**2 или просто np.linalg.norm для расчета обычного расстояния.Это также может быть полезно для других векторных арифметических операций.

1 голос
/ 10 апреля 2019

В Python многопоточность не увеличивает количество используемого ядра. Вместо этого вы должны использовать многопроцессорность.
Документ: https://docs.python.org/3.7/library/multiprocessing.html#multiprocessing.Manager

...