Управление памятью Python при обработке больших изображений - PullRequest
0 голосов
/ 07 ноября 2018

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

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

def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True):
    CFA = np.asarray(CFA)
    R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern)

    h_0 = np.array([0, 0.5, 0, 0.5, 0])
    h_1 = np.array([-0.25, 0, 0.5, 0, -0.25])

    R = CFA * R_m
    G = CFA * G_m
    B = CFA * B_m

    G_H = np.where(G_m == 0, _cnv_h(CFA, h_0) + _cnv_h(CFA, h_1), G)
    G_V = np.where(G_m == 0, _cnv_v(CFA, h_0) + _cnv_v(CFA, h_1), G)

    C_H = np.where(R_m == 1, R - G_H, 0)
    C_H = np.where(B_m == 1, B - G_H, C_H)

    C_V = np.where(R_m == 1, R - G_V, 0)
    C_V = np.where(B_m == 1, B - G_V, C_V)

    D_H = np.abs(C_H - np.pad(C_H, ((0, 0), (0, 2)),
                            mode=str('reflect'))[:, 2:])
    D_V = np.abs(C_V - np.pad(C_V, ((0, 2), (0, 0)),
                            mode=str('reflect'))[2:, :])

    k = np.array(
        [[0, 0, 1, 0, 1],
        [0, 0, 0, 1, 0],
        [0, 0, 3, 0, 3],
        [0, 0, 0, 1, 0],
        [0, 0, 1, 0, 1]])  # yapf: disable

    d_H = convolve(D_H, k, mode='constant')
    d_V = convolve(D_V, np.transpose(k), mode='constant')

    mask = d_V >= d_H
    G = np.where(mask, G_H, G_V)
    M = np.where(mask, 1, 0)

    # Red rows.
    R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape)
    # Blue rows.
    B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape)

    k_b = np.array([0.5, 0, 0.5])

    R = np.where(
        np.logical_and(G_m == 1, R_r == 1),
        G + _cnv_h(R, k_b) - _cnv_h(G, k_b), R)

    R = np.where(
        np.logical_and(G_m == 1, B_r == 1) == 1,
        G + _cnv_v(R, k_b) - _cnv_v(G, k_b), R)

    B = np.where(
        np.logical_and(G_m == 1, B_r == 1),
        G + _cnv_h(B, k_b) - _cnv_h(G, k_b), B)

    B = np.where(
        np.logical_and(G_m == 1, R_r == 1) == 1,
        G + _cnv_v(B, k_b) - _cnv_v(G, k_b), B)

    R = np.where(
        np.logical_and(B_r == 1, B_m == 1),
        np.where(M == 1, B + _cnv_h(R, k_b) - _cnv_h(B, k_b),
                B + _cnv_v(R, k_b) - _cnv_v(B, k_b)), R)

    B = np.where(
        np.logical_and(R_r == 1, R_m == 1),
        np.where(M == 1, R + _cnv_h(B, k_b) - _cnv_h(R, k_b),
                R + _cnv_v(B, k_b) - _cnv_v(R, k_b)), B)

    RGB = tstack((R, G, B))

    if refining_step:
        RGB = refining_step_Menon2007(RGB, tstack((R_m, G_m, B_m)), M)

    return RGB

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

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

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