Уменьшите использование памяти при выполнении операций с массивом Numpy - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть довольно большой массив NumPy, с которым мне нужно выполнить операцию, но когда я это делаю, мой ~ 2 ГБ массив требует ~ 30 ГБ ОЗУ для выполнения операции.Я читал, что NumPy может быть довольно неуклюжим с использованием памяти, но это кажется чрезмерным.

Кто-нибудь знает альтернативный способ применения этих операций для ограничения загрузки ОЗУ?Возможно построчно / на месте и т. Д .?

Код ниже (игнорируйте бессмысленные вычисления, в моем коде коэффициенты различаются):

import xarray as xr 
import numpy as np

def optimise(data):

    data_scaled_offset = (((data - 1000) * (1 / 1)) + 1).round(0)
    return data_scaled_offset.astype(np.uint16)

# This could also be float32 but I'm using uint16 here to reduce memory load for demo purposes
ds = np.random.randint(0, 12000, size=(40000,30000), dtype=np.uint16)

ds = optimise(ds) # Results in ~30GB RAM usage

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Вы можете использовать, например.Numba или Cython, чтобы уменьшить использование памяти.Конечно, простой цикл Python также возможен, но очень медленный.

С выделенным выходным массивом

import numpy as np
import numba as nb

@nb.njit()
def optimise(data):
    data_scaled_offset=np.empty_like(data)
    # Inversely apply scale and scale and offset for this product
    for i in range(data.shape[0]):
        for j in range(data.shape[1]):
            data_scaled_offset[i,j] = np.round_((((data[i,j] - 1000) *(1 / 1)) + 1),0)

    return data_scaled_offset

На месте

@nb.njit()
def optimise_in_place(data):
    # Inversely apply scale and scale and offset for this product
    for i in range(data.shape[0]):
        for j in range(data.shape[1]):
            data[i,j] = np.round_((((data[i,j] - 1000) *(1 / 1)) + 1),0)

    return data
1 голос
/ 24 сентября 2019

По умолчанию такие операции, как умножение, сложение и многие другие ... вы можете использовать numpy.multiply, numpy.add и использовать параметр out, чтобы использовать существующий массив для хранения результата.Это значительно уменьшит использование памяти.Пожалуйста, ознакомьтесь с демонстрацией ниже и переведите свой код для использования этих функций вместо

arr = np.random.rand(100)
arr2 = np.random.rand(100)

arr3 = np.subtract(arr, 100, out=arr)
arr4 = arr+100
arr5 = np.add(arr, arr2, out=arr2)
arr6 = arr+arr2

print(arr is arr3) # True
print(arr is arr4) # False
print(arr2 is arr5) # True
print(arr2 is arr6) # False
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...