#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. О, боже, это потрясающе, очень здорово.