Повышение производительности за счет использования нескольких потоков/ядер

У меня есть игра (использующая 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

Вы сможете увеличить вычислительную мощность только в том случае, если у вас есть все доступные объекты для многопроцессорность, готовые и поставленные в очередь, поэтому, если вы генерируете по одному или нуждаетесь в нем для заказа, это будет сложнее. Также имейте в виду, что Python действительно плохо справляется с этой параллельной работой, и этот «официальный» хак должен быть реализован осторожно, как показано (особенно для Windows), иначе он приведет к зависанию либо приложения, либо всей вашей машины. Вместо этого можно попробовать оптимизировать.

lucasgcb 10.04.2019 15:28
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
1
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Ответ принят как подходящий

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

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

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

  • Сохраняйте индекс сущностей по типу (например, словарь от типа сущности к набору сущностей, который вы обновляете по мере создания/удаления сущностей), что позволит вам легко находить все сущности «еда» без сканирования всех сущностей в игра.
  • Найдите ближайший пищевой объект, используя простую операцию «минимум» (это 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 для обычного вычисления расстояния. Это также может быть полезно для других векторных арифметических операций.

Другие вопросы по теме