Есть ли способ заменить цикл for чем-то более эффективным в python? - PullRequest
0 голосов
/ 20 мая 2018

Мой код ниже проверяет окружающие пиксели на пиксель моего объекта в python.

self.surr = [None, None, None, None, None, None, None, None]

for i in range(9):
#for x in range(-1, 2):
    #for y in range(-1, 2):
        if i != 5:
            x = i % 3 - 2
            y = int((i % 3) / 3) - 1

        if x == 0 and y == 0:
            pass
        else:
            PAI = allPixels[(self.x + x) % width][(self.y + y) % height] if allPixels[(self.x + x) % width][(self.y + y) % height] != None else None

        self.surr[(y * 3) + x] = (PAI)

return self.surr

Возвращает список длиной 8, который содержит либо Pixel объект, либо None.allPixels - это двумерный массив, который также содержит объект Pixel или None.Затем я попробовал вложенные циклы, которые закомментированы, но они работают немного медленнее, чем метод, который я сейчас использую.Это, однако, все еще слишком медленно, как если бы на экране было 3000 пикселей, что является нижним пределом общего количества пикселей, которые будут на экране в конце, сделайте математику, и у вас будет LOT на каждом кадре.

Как я могу сделать это быстрее, используя NumPy или другой метод?

Если вы хотите увидеть весь код, его можно найти здесь: https://pastebin.com/EuutUVjS

Спасибо за любую помощь, которую вы можете мне оказать!

1 Ответ

0 голосов
/ 20 мая 2018

То, что вы делаете по своей сути, требует зацикливания, но если вы сможете переместить это зацикливание в ноль, оно часто будет ускоряться в 5-20 раз.

В вашем случае вы пытаетесь сделать следующее:сравнить каждый пиксель с его соседями.Как вы можете сделать это как операцию всего массива?Просто: сравните массив с тем же массивом, смещенным на 1.

Вот более простой пример:

>>> a = np.array([1,2,4,8,16])
>>> for i in range(1, len(a)):
...     print(a[i] - a[i-1], end=' ')
1 2 4 8
>>> print(a[1:] - a[:-1])
[1 2 4 8]

Итак, для двумерного массива это просто:

north = a[:-1]
ne = a[:-1,1:]
east = a[:,1:]
se = a[1:,1:]
south = a[1:]
sw = a[1:,:-1]
west = a[:,:-1]
nw = a[:-1,:-1]

Обратите внимание, что это не тратит много времени и памяти не создает 8 дополнительных массивов;он просто создает 8 представлений над одной и той же памятью.

См. этот ответ на compsci , где приведен пример использования этих сдвинутых массивов для симуляции Conway Game of Life.

Есливы хотите обрабатывать границы по-разному, вам может понадобиться «растянуть ноль» массива, но это единственная сложность, с которой вы, вероятно, столкнетесь.


Однако есть предел тому, скольковы можете получить выгоду от numpy, если храните в нем объекты Python.Обычно вы хотите хранить массивы чисел.

Я не знаю, что находится в ваших Pixel объектах, но давайте представим, что это просто значения цвета, как три числа с плавающей запятой.В этом случае вы можете использовать 2D-массив со структурированным d-типом из трех чисел с плавающей запятой или просто 3D-массив (строка за столбцом по rgb), в любом случае используйте значения NaN вместо None.

ЕслиВы делаете это, операции в массиве могут работать на почти машинных скоростях, включая использование SIMD-операций для параллелизма данных.Если нет, то только зацикливание происходит на родных скоростях;арифметика внутри цикла все еще такая же медленная, как в не-Numpy Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...