Numpy repack_fields с диапазоном или списком выделяет память

Проблема:

Я пытаюсь переупаковать подмножество строк и полей из большого структурированного массива numpy.

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

Пример:

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

import numpy as np
from numpy.lib.recfunctions import repack_fields
import resource

resource.setrlimit(resource.RLIMIT_AS, (int(1.5e9), int(1.5e9)))

H = np.zeros(100, dtype=[('f1', int), ('f2', int), ('large', float, 1000000)])

print('Using slicing: ')
repack_fields(H[['f1', 'f2']][0:50])
print('Using range: ')
repack_fields(H[['f1', 'f2']][range(0, 50)])

производит вывод:

Using slicing: 
Using range: 
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    repack_fields(H[['f1', 'f2']][range(0, 50)])
MemoryError: Unable to allocate 381. MiB for an array with shape (50,) and data type {'names':['f1','f2'], 'formats':['<i8','<i8'], 'offsets':[0,8], 'itemsize':8000016}

Вопросы:

  1. Почему поведение range(0, 50) отличается от поведения 0:50? (Список также не работает.) Я знаю, что в приведенном выше примере можно сначала переупаковать поля, а затем ссылаться на строки. (То есть repack_fields(H[['f1', 'f2']])[range(0, 50)] работает.) Но я не хочу знать, лучше ли сначала получить строки или сначала поля.

  2. Как правильно взять подмножество строк/полей из большого структурированного массива numpy? (даже если строки не являются последовательными)?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
101
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
repack_fields(H[['f1', 'f2']][0:50])

И [['f1', 'f2']], и [0:50] производят view, один потому, что это индекс с несколькими полями, а другой, потому что это срез (базовое индексирование). Так что не требует новой памяти. repack_fields создает новый массив с местом только для этих 2 полей и 50 записей и копирует значения из view.

repack_fields(H[['f1', 'f2']][range(0, 50)])

Опять же, индекс полей — это view, ссылающийся на всю структуру, включая поле large. [range...] — это расширенное индексирование, создание копии, включающей 50 записей «крупного размера».

Посмотрите на ошибку:

 Unable to allocate 381. MiB for an array with shape (50,) and data type
 {'names':['f1','f2'], 'formats':['<i8','<i8'], 'offsets':[0,8], 'itemsize':8000016}

 In [336]: 50*8000016/1e6
 Out[336]: 400.0008

Это 381 МБ, которые он пытается выделить. Ошибка возникает при индексации [range(50)]. До репака еще не дошло.

Итак, вы должны понять две вещи.

  • Индексирование с помощью среза создает view, который не потребляет дополнительную память. Индексирование с помощью range или списка (или массива) является «расширенным индексированием» и создает копию.

  • индексация с несколькими полями делает view. Даже если поля являются подмножеством источника, размер элемента остается исходным. Целью repack является создание нового массива с новым dtype и новым размером элемента, содержащего только значения для выбранных полей.

Знаете ли вы, как правильно получить подмножество (непоследовательных) строк в виде представления?

jmlarson 12.12.2020 02:10

Нет ни одного. Представление возможно только тогда, когда память является последовательной или может быть идентифицирована шагами (как в случае среза с шагом). Это касается всех массивов.

hpaulj 12.12.2020 02:58

Другие вопросы по теме