Как мне присоединиться к ссылкам numpy?

#python #numpy

#python #numpy

Вопрос:

Я часто использую SoA для ускорения, но я хотел бы иметь возможность ссылаться на них как на просто массив. Если я могу выбрать фрагмент всего элемента, как nda[:]['a'][:] это делает for a , есть ли способ создать плоскую ссылку на все эти элементы?

 import numpy as np

WARP_SIZE = 4

dt = np.dtype([('a', (np.float64, WARP_SIZE)),  ('b', (np.float64, WARP_SIZE))])
nda = np.ndarray(3, dtype=dt)
nda[:] = 0
a_vals = nda[:]['a'][:]
a_vals[0:2] = 3
print(nda)
nda[:] = 0
a_vals.flatten()[0:2] = 3
print(nda)
  

Комментарии:

1. Что означает SoA в этом контексте?

2. Кроме того, что такое «плоская ссылка»?

3. SoA = Структура массивов. en.wikipedia.org/wiki/AoS_and_SoA и под плоским я подразумеваю изменение формы ссылки array([[0., 0., 0., 0.],[0., 0., 0., 0.],[0., 0., 0., 0.]]) на плоский vec, равный 12.

4. Обязательный глупый вопрос: вам действительно нужны структурированные массивы? Разве вы не можете просто использовать столбцы / фрагменты многомерного массива?

5. Я не видел этого синтаксиса, в котором структурированные кортежи dtype содержат кортежи внутри, поэтому я предполагаю, что именно поэтому вам нужны повторные выборки.

Ответ №1:

Вот мой взгляд на вашу проблему:

 a_vals = nda['a']  # should be the same as yours
a_vals_flat = a_vals.reshape(-1)  # flattened a_vals
a_vals_flat.base is a_vals  # False!
  

Таким образом, вы можете получить представление о полях, помеченных 'a' с nda['a'] помощью, это нормально. Однако, когда вы сглаживаете этот массив, вы больше не получаете представление в свой предыдущий массив. Вероятно, это связано с тем, что массив не является непрерывным:

 >>> a_vals.flags
  C_CONTIGUOUS : False
  F_CONTIGUOUS : False
  OWNDATA : False
  WRITEABLE : True
  ALIGNED : True
  WRITEBACKIFCOPY : False
  UPDATEIFCOPY : False
  

Мы можем воспроизвести это поведение с несмежным представлением обычного массива:

 arr = np.arange(2*3*4).reshape(3, 2, 4)[:, 0, :]  # shape (3, 4)
arr_flat = arr.reshape(-1)
print(arr_flat.base is arr)  # False

arr_flat[:] = -1

print(arr)
# [[ 0  1  2  3]
#  [ 8  9 10 11]
#  [16 17 18 19]]
  

Вместо этого вы можете использовать .flat flatiter атрибут. У меня есть смутные воспоминания об этом, которые могут привести к проблемам, поэтому обращайтесь с осторожностью. Но, похоже, это работает:

 import numpy as np 
 
WARP_SIZE = 4 
 
dt = np.dtype([('a', (np.float64, WARP_SIZE)),  ('b', (np.float64, WARP_SIZE))])
nda = np.zeros(3, dtype=dt) 
a_vals = nda['a'] 
a_vals_flat = a_vals.flat 
nda[:] = 0 
a_vals_flat[0:2] = 3 
print(nda)      
# [([3., 3., 0., 0.], [0., 0., 0., 0.]) ([0., 0., 0., 0.], [0., 0., 0., 0.])
#  ([0., 0., 0., 0.], [0., 0., 0., 0.])]
  

Комментарии:

1. О, боже, это потрясающе, очень здорово.