Как ускорить for в for?
Имеется h5 файл
Открываю его:
fh = h5py.File(file, 'r')
X = fh["lat"][:, :]
Y = fh["lon"][:, :]
ch3 = fh["3b"][:, :][1000:1500, 1000:1500] # Кусок чтобы не ждать вечность.
Затем хочу пробежаться по этому куску массива матрицей 3x3 чтобы выделить пожарные точки.
matrxSise = 3 # Размер матрицы
centr = int((matrxSise + 1) / 2) - 1 # Центр матрицы
T3b = search_fire_points(ch3, centr, matrxSise)
def search_fire_points(M, centr, matrxSise):
"""
Функция поиска пожарных точек больше > 310K.
"""
y, x = M.shape
T3b = np.empty([y - centr - 1, x - centr - 1]) # Пустой массив
for i in range(y - centr - 2):
for j in range(x - centr - 2):
m = M[i:(i + matrxSise), j:(j + matrxSise)]
Tij = m[centr, centr]
m[centr, centr] = 0.0
ma = np.ma.masked_equal(m, 0.0, copy=False)
meanQ = np.mean(ma) # Считаем mean в матрице
stdQ = np.std(ma) # Считаем std в матрице
if (Tij > (meanQ + 3 * stdQ)) & (Tij > 310): # Всё что больше пика и > 310 градусов - пожар
T3b[i + centr, j + centr] = 1000
else:
T3b[i + centr, j + centr] = 0
return T3b
Пожарные точки выделены. Но занимает перебор - очень много. А если представить полный массив размером 6000x6000 то операция занимает около часа.
Как можно ускорить перебор всего массива, или изменить алгоритм перебора, чтобы проход был быстрее?
UPD
Небольшая оптимизация
def search_fire_points(M, matrxSise=3):
centr = int((matrxSise + 1) / 2) - 1
y, x = M.shape
# T3b = np.empty([y - centr - 1, x - centr - 1])
T3b = np.full([y, x], fill_value=False)
for i in range(y - centr - 2):
for j in range(x - centr - 2):
m = M[i:(i + matrxSise), j:(j + matrxSise)]
Tij = m[centr, centr]
m[centr, centr] = np.nan
# ma = np.ma.masked_equal(m, 0.0, copy=False)
meanQ = np.nanmean(m)
stdQ = np.nanstd(m)
if Tij > 305:
if Tij > (meanQ + 3 * stdQ):
T3b[i + centr, j + centr] = True
return T3b
Файл: https://nc.rcpod.space/index.php/s/QzJCSg8T3YLQyDw
Ответы (1 шт):
Автор решения: GrAnd
→ Ссылка
Вот такой код на вашем файле отрабатывает за 21 секунду на моём 11-летнем компе. (против 20 минут вашей функции)
def search_fire_points_fast3(M, matrxSise=3, treshold=305):
centr = (matrxSise + 1) // 2 - 1
y, x = M.shape
T3b = np.full([y, x], fill_value=False)
for i,j in zip(*np.where(M[centr:y-centr, centr:x-centr] > treshold)):
m = M[i:i+matrxSise, j:j+matrxSise].copy()
Tij = m[centr, centr]
m[centr, centr] = np.nan
meanQ = np.nanmean(m)
stdQ = np.nanstd(m)
if Tij > (meanQ + 3 * stdQ):
T3b[i + centr, j + centr] = True
return T3b