Как повысить производительность при интерполяции 3D-данных с помощью SciPy

У меня есть 3D-данные, представляющие атмосферу. Теперь я хочу интерполировать эти данные в общую координату Z (что я подразумеваю под этим, должно быть ясно из описания функции). Следующий код работает нормально, но мне было интересно, есть ли способ улучшить производительность...

def interpLevel(grid,value,data,interp='linear'):
    """
    Interpolate 3d data to a common z coordinate.

    Can be used to calculate the wind/pv/whatsoever values for a common
    potential temperature / pressure level.

    grid : numpy.ndarray
       The grid. For example the potential temperature values for the whole 3d
       grid.

    value : float
       The common value in the grid, to which the data shall be interpolated.
       For example, 350.0

    data : numpy.ndarray
       The data which shall be interpolated. For example, the PV values for
       the whole 3d grid.

    kind : str
       This indicates which kind of interpolation will be done. It is directly
       passed on to scipy.interpolate.interp1d().

    returs : numpy.ndarray
       A 2d array containing the *data* values at *value*.

    """
    ret = np.zeros_like(data[0,:,:])
    # we need to copy the grid to a new one, because otherwise the flipping
    # done below will be messed up
    gr = np.zeros_like(grid)
    da = np.zeros_like(data)
    for latIdx in xrange(grid.shape[1]):
        for lonIdx in xrange(grid.shape[2]):
            # check if we need to flip the column
            if grid[0,latIdx,lonIdx] > grid[-1,latIdx,lonIdx]:
                gr[:,latIdx,lonIdx] = grid[::-1,latIdx,lonIdx]
                da[:,latIdx,lonIdx] = data[::-1,latIdx,lonIdx]
            else:
                gr[:,latIdx,lonIdx] = grid[:,latIdx,lonIdx]
                da[:,latIdx,lonIdx] = data[:,latIdx,lonIdx]
            f = interpolate.interp1d(gr[:,latIdx,lonIdx], \
                    da[:,latIdx,lonIdx], \
                    kind=interp)
            ret[latIdx,lonIdx] = f(value)
    return ret

person andreas-h    schedule 22.02.2010    source источник


Ответы (1)


Что ж, это может дать небольшое ускорение только потому, что использует меньше памяти.

ret = np.zeros_like(data[0,:,:])
for latIdx in xrange(grid.shape[1]):
    for lonIdx in xrange(grid.shape[2]):
        # check if we need to flip the column
        if grid[0,latIdx,lonIdx] > grid[-1,latIdx,lonIdx]:
            ind = -1
        else:
            ind = 1
        f = interpolate.interp1d(grid[::ind,latIdx,lonIdx], \
                data[::ind,latIdx,lonIdx], \
                kind=interp)
        ret[latIdx,lonIdx] = f(value)
return ret

Все, что я сделал, это избавился от gr и da на самом деле.

Кроме того, вызываете ли вы эту функцию с большим количеством разных значений (т.е. значение отличается, но другие параметры одинаковы)? Если это так, вы можете захотеть, чтобы функция могла обрабатывать несколько значений (другими словами, добавьте еще одно измерение в ret, длина которого равна длине значений). Тогда вы лучше используете созданную вами функцию интерполяции.

Последнее предложение — попробовать профилировщик. Это позволит вам увидеть, что занимает больше всего времени.

person Justin Peel    schedule 22.02.2010
comment
Вы также можете уменьшить один из двух внешних циклов, используя np.ndenumerate. Это также должно немного ускорить процесс. - person Jose; 23.04.2011