Ускорить присвоение массивов с помощью списка или отображения? - PullRequest
0 голосов
/ 26 сентября 2018

Я пытаюсь добавить значения маленького двумерного массива («источник») в больший двумерный массив («кадр»), начиная с определенной позиции в массиве кадров («pos_x», «pos_y ").Прямо сейчас у меня есть два цикла for, добавляющих значение источника к значению кадра в каждой позиции:

for i in range(x):
    for j in range(y):
        frame[pos_x+i][pos_y+j] += source[i][j]

(«x» и «y» - это форма исходных массивов)

Однако массивы довольно велики (форма массива кадров: 5000x8000 и форма массива источника: 1000x5000).Таким образом, этот процесс занимает довольно много времени (около 15 секунд).

Есть ли способ ускорить этот процесс, либо через понимание списка, либо через отображение, либо еще что-нибудь?

Я пытался понять списки, как это, с несколькими утверждениями и назначениями:

frame = [[frame[pos_x+i][pos_y+j] + source[i][j] for j in range(y)] for i in range(x)]

(адаптировано из потоков: Как я могу выполнять назначения в понимании списка? и Несколько операторов в списках в Python? )

, но это занимает столько же времени, сколько и в исходных циклах for.

Другая идея состояла в том, чтобы разрешить цикл только для ненулевых значений с if source[i][j] != 0.Но когда я попробовал это, это заняло в три раза больше времени (потенциальный подвопрос: есть идеи почему?).

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Вы можете воспользоваться преимуществами векторизации здесь вместо циклического ускорения.Это всего лишь вопрос расчета индексов и проверки того, выходите ли вы за пределы.

height, width = source.shape
pos_x2 = pos_x + width
pos_y2 = pos_y + height
#check for possible index out of range
fheight, fwidth = frame.shape
if pos_x2 > fwidth or pos_y2 > fheight:
    print('source out of frame bounds')
else:
    #add `source` to our slice of `frame`
    frame[pos_y:pos_y2, pos_x:pos_x2] += source

Хотя технически это будет иметь одинаковую сложность по времени, numpy использует эффективный скомпилированный код C, который может использовать преимущества таких вещей, какаппаратная векторизация и не имеет все накладные расходы интерпретатора Python.

0 голосов
/ 26 сентября 2018

фрагменты изменчивы в numpy;так что вы можете делать такие вещи, как:

import numpy as np

A = np.zeros((10,10), int)
B = np.zeros((5,5), int) + 5

A[2:7,2:7] += B

print(A)
...