Как ускорить 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
→ Ссылка