2016-12-16 2 views
0

У меня есть массив 601x350x200x146 numpy float64, который, согласно моим вычислениям, занимает около 22,3 Гб памяти. Мой вывод free -m говорит мне, что у меня есть около 100 ГБ свободной памяти, чтобы он соответствовал штрафу. Однако при интеграции сИзбегайте ошибок памяти при интеграции большого массива с Numpy

result = np.trapz(large_arr, axis=3) 

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

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

Другие используют операторы *=, такие как запись arr*=a вместо arr=arr*a, что я действительно не могу здесь сделать. Поэтому я не знаю, что еще попробовать.

Кто-нибудь знает, как сделать эту операцию без повышения ошибки памяти?

Вы можете воспроизвести ошибку с:

arr = np.ones((601,350,200,146), dtype=np.float64) 
arr=np.trapz(arr, axis=3) 

хотя вам придется уменьшать размер, чтобы соответствовать размеру памяти.

+2

Мне кажется, что этот массив составляет 49 гигабайт. NumPy много использует массивы промежуточных царапин; для реализации 'np.trapz' требуется больше тех, которые могут храниться в вашей памяти. – user2357112

+0

Знаете ли вы, что делает 'trapz'? Даже если '' arr' сам подходит, временные массивы, созданные 'trapz', могут и не быть. – hpaulj

+0

@ user2357112 Да, вот что я подумал. Но что вы говорите, это просто нет? – TomCho

ответ

3

numpy.trapz обеспечивает некоторое удобство, но фактический расчет очень прост. Для того, чтобы избежать больших временных массивов, просто реализовать его самостоятельно:

In [37]: x.shape 
Out[37]: (2, 4, 4, 10) 

Вот результат numpy.trapz(x, axis=3):

In [38]: np.trapz(x, axis=3) 
Out[38]: 
array([[[ 43. , 48.5, 46.5, 67. ], 
     [ 35.5, 39.5, 52.5, 35. ], 
     [ 44.5, 47.5, 34.5, 39.5], 
     [ 54. , 40. , 46.5, 50.5]], 

     [[ 42. , 60. , 55.5, 51. ], 
     [ 51.5, 40. , 52. , 42.5], 
     [ 48.5, 43. , 32. , 36.5], 
     [ 42.5, 38. , 38. , 45. ]]]) 

Вот расчет написано не использовать не больших промежуточных массивов. (Срез x[:,:,:,1:-1] не копирует данные, связанные с массивом.)

In [48]: 0.5*(x[:,:,:,0] + 2*x[:,:,:,1:-1].sum(axis=3) + x[:,:,:,-1]) 
Out[48]: 
array([[[ 43. , 48.5, 46.5, 67. ], 
     [ 35.5, 39.5, 52.5, 35. ], 
     [ 44.5, 47.5, 34.5, 39.5], 
     [ 54. , 40. , 46.5, 50.5]], 

     [[ 42. , 60. , 55.5, 51. ], 
     [ 51.5, 40. , 52. , 42.5], 
     [ 48.5, 43. , 32. , 36.5], 
     [ 42.5, 38. , 38. , 45. ]]]) 

Если x имеет форму (m, n, p, q), несколько временных массивов, которые создаются в этом выражении все имеют форму (m, n, p).

+0

А, конечно. Мы можем уменьшить размеры сразу, а не на последнем шаге. Вы можете исключить оставшиеся временные массивы с помощью '+ =' и '* =', что может быть немного полезно при сокращении по короткой оси, но экономия памяти небольшая по сравнению с размером ввода и размером ' нп.временные паузы. – user2357112